Fare Django forms.DateField spettacolo utilizzo formato data locale
Domanda
Sto cercando di trovare un modo semplice per costruire forme che mostrano le date nel formato australiano (gg / mm / aaaa). Questo era l'unico modo che ho trovato per farlo. Sembra che ci dovrebbe essere una soluzione migliore.
Cose da notare:
- Creato un nuovo widget che rende valore di data nel formato gg / mm / aaaa
- Creato nuovo campo data per anteporre la data stringa di localizzare formato l'elenco dei valori che tenta di utilizzare
Immagino che la soluzione ideale sarebbe un DateField che localizzata automaticamente, ma che non ha funzionato per me (strftime non sembra essere unicode cordiale, ma non ho provato molto duro)
Mi sto perdendo qualcosa? C'è una soluzione più elegante? E 'questo un approccio robusto?
from models import *
from django import forms
import datetime
class MyDateWidget(forms.TextInput):
def render(self, name, value, attrs=None):
if isinstance(value, datetime.date):
value=value.strftime("%d/%m/%Y")
return super(MyDateWidget, self).render(name, value, attrs)
class MyDateField(forms.DateField):
widget = MyDateWidget
def __init__(self, *args, **kwargs):
super(MyDateField, self).__init__(*args, **kwargs)
self.input_formats = ("%d/%m/%Y",)+(self.input_formats)
class ExampleForm(ModelForm):
class Meta:
model=MyModel
fields=('name', 'date_of_birth')
date_of_birth = MyDateField()
Soluzione
Certo, io non sono un Django / Python Jedi, ma ...
Non credo che ci sia qualcosa di sbagliato con il vostro approccio. Si tratta di una lettura pulita.
Non potrebbe essere necessario creare il tuo widget solo per rendere la data nel formato corretto sul primo display modulo. Basta usare il parametro format
per il widget DateInput
e si dovrebbe essere OK. Quindi, nella tua classe MyDateField Vorrei solo fare:
class MyDateField(forms.DateField):
widget = forms.DateInput(format="%d/%m/%Y")
def __init__(self, *args, **kwargs):
super(MyDateField, self).__init__(*args, **kwargs)
self.input_formats = ("%d/%m/%Y",)+(self.input_formats)
Si potrebbe utilizzare formfield_callback
(Vedere la accettato risposta per questa domanda lontani parenti), che significa:
def customize_fields(f):
if isinstance(f, DateTimeField):
datetime_field=forms.DateTimeField(widget=
forms.DateInput(format='%d/%m/%Y %h:%i'))
date_field.input_formats = ("%d/%m/%Y %h:%i",)+
(date_field.input_formats)
return datetime_field
elif isinstance(f, DateField):
date_field=forms.DateField(widget=
forms.DateInput(format='%d/%m/%Y'))
date_field.input_formats = ("%d/%m/%Y",)+
(date_field.input_formats)
return date_field
else:
return f.formfield()
class MyModelForm(forms.ModelForm):
formfield_callback = customize_fields
class Meta:
model = ...
In questo che elimina completamente la necessità per la classe MyDateField
, ma potrebbe introdurre - se si desidera che ogni singola classe form per chiamare customize_fields
-. La necessità di un discendente ModelForm, attuazione formfield_callback=customize_fields
come la nuova base per tutte le classi dei form
Il mio problema con l'utilizzo del meccanismo di formfield_callback
è duplice:
-
E 'meno leggibile e si basa nella conoscenza del funzionamento interno di ModelForms. Non riesco a trovare la documentazione reale sul formfield_callback ovunque ...
-
Se hai bisogno di ridefinire un campo modello in un ModelForm, dire a rendere il campo non richiesto per quel particolare istanza del modulo, in questo modo:
class MyModelForm(forms.ModelForm): formfield_callback = customize_fields foo = forms.DateField(required=false) class Meta: model = Bar
si sovrascrive il campo di modulo restituito da customize_fields, quindi perdere completamente la personalizzazione.
Credo che il tuo approccio è più leggibile.
Altri suggerimenti
Ho usato questo approccio semplice prima: basta impostare l'attributo 'format' del DateField.widget nel INIT del modulo:
class ExampleForm(ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(ModelForm, self).__init__(*args, **kwargs)
self.fields['date_of_birth'].widget.format = '%d/%m/%Y'
# at the same time, set the input format on the date field like you want it:
self.fields['date_of_birth'].input_formats = ['%d/%m/%Y']
Tutte le cose widget personalizzato può essere escluso.
Ecco un estratto da django/forms/widgets.py
:
class DateInput(TextInput):
def __init__(self, attrs=None, format=None):
super(DateInput, self).__init__(attrs)
if format:
self.format = format
self.manual_format = True
else:
self.format = formats.get_format('DATE_INPUT_FORMATS')[0]
self.manual_format = False
Si noterà che il formato del widget viene impostato utilizzando il modulo in formato. Il modulo formato viene selezionato a seconda del locale. Se si sta navigando dagli Stati Uniti, Django, per impostazione predefinita, selezionare django.conf.formats.locale.en.formats.py
. Qui troverete il formato predefinito:
DATE_INPUT_FORMATS = (
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
# '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
# '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
# '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
# '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
)
Come si può vedere nel primo blocco di codice, Django seleziona il primo di questi. L'approccio approfondito per cambiare il formato è quello di creare il proprio modulo in formato, sovrascrivendo di default di Django per il locale in questione. Per questo, guardare in FORMAT_MODULE_PATH . Se tutti si sta cercando di fare è ignorare il formato predefinito di data, dico risparmiare tempo e la patch scimmia. Ho aggiunto questo al mio file di impostazioni e tutto sembra funzionare splendidamente con il mio formato di default preferito:
DATE_INPUT_FORMATS = ('%m/%d/%Y', '%m/%d/%y', '%Y-%m-%d',
'%b %d %Y', '%b %d, %Y', '%d %b %Y',
'%d %b, %Y', '%B %d %Y', '%B %d, %Y',
'%d %B %Y', '%d %B, %Y')
from django.conf.locale.en import formats
formats.DATE_INPUT_FORMATS = DATE_INPUT_FORMATS
Nella mia forma I'me utilizzando:
def today():
from datetime import date
return date.today().strftime("%d.%m.%Y")
when = models.DateField(u'Когда', default=today)