Machen Django forms.DateField zeigt die Verwendung lokales Datumsformat
Frage
Ich versuche, eine einfache Möglichkeit zu finden, Formen zu bauen, die Termine im australischen Format anzeigen (dd / mm / jjjj). Dies war die einzige Art, wie ich es tun finden. Es scheint, wie es sollte eine bessere Lösung.
Dinge zu beachten:
- ein neues Widget Erstellt der Datumswert in tt / mm / jjjj Format rendert
- neues Datumsfeld Erstellt das orten Datumsformat-Zeichenfolge in die Liste der Werte vorangestellt wird, es zu benutzen versucht,
Ich stelle mir die ideale Lösung ein Datefield sein würde, die automatisch lokalisiert, aber das funktionierte nicht für mich arbeiten (strftime nicht Unicode zu sein schien freundlich, aber ich versuche, nicht sehr hart)
Bin ich etwas fehlt? Gibt es eine elegantere Lösung? Ist das ein robusterer Ansatz?
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()
Lösung
Zugegeben, ich bin kein django / Python Jedi, aber ...
Ich glaube nicht, dass es etwas falsch mit Ihrem Ansatz. Es ist eine saubere lesen.
Sie benötigen kein eigenes Widget zu erstellen, das Datum im richtigen Format auf der ersten Form Anzeige zu machen. Verwenden Sie einfach die format
Parameter für die DateInput
Widget und Sie sollten in Ordnung sein. Ich würde also in Ihrer MyDateField Klasse gerade tun:
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)
könnten Sie verwenden formfield_callback
(Siehe akzeptierte Antwort für diese weitläufig verwandt Frage), was bedeutet:
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 = ...
Dadurch, dass vollständig die Notwendigkeit für Ihre MyDateField
Klasse beseitigt, aber vorstellen könnte - wenn man jede einzelne Formularklasse will customize_fields
nennen -. Die Notwendigkeit eine Modelform Nachkommen, formfield_callback=customize_fields
als neue Basis der Umsetzung für alle Formularklassen
Mein Problem des formfield_callback
Mechanismus bei der Verwendung ist zweifach:
-
Es ist weniger lesbar und verlässt sich in Kenntnis der inneren Abläufe ModelForms. Ich kann nicht unbedingt der Dokumentation auf formfield_callback finden überall ...
-
Wenn Sie jemals ein Modellfeld in einer Modelform neu zu definieren müssen, sagen, um das Feld zu machen nicht für diese bestimmte Instanz des Formulars erforderlich, etwa so:
class MyModelForm(forms.ModelForm): formfield_callback = customize_fields foo = forms.DateField(required=false) class Meta: model = Bar
Sie überschreiben das Formularfeld durch customize_fields zurückgegeben, daher vollständig die Anpassung zu verlieren.
Ich denke, Ihr Ansatz ist besser lesbar.
Andere Tipps
Ich habe diesen einfachen Ansatz vor: nur das ‚Format‘ Attribut des DateField.widget im init des Formulars:
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']
Alle benutzerdefinierten Widget Sachen können umgangen werden.
Hier ist ein Auszug aus 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
Sie werden bemerken, dass das Format des Widgets festgelegt wird, um das Format-Modul. Das Format-Modul wird in Abhängigkeit von dem Lokalisierungs ausgewählt. Wenn Sie aus den USA surfen, Django, die standardmäßig wählen django.conf.formats.locale.en.formats.py
. Hier finden Sie das Standardformat finden:
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'
)
Wie Sie in dem ersten Codeblock sehen, wählt Django die ersten davon. Der gründliche Ansatz um das Format zu ändern, ist ein eigenes Format Modul zu erstellen, für das Gebietsschema in Frage Djangos Standard zu überschreiben. Dazu schauen Sie in FORMAT_MODULE_PATH . Wenn alle Sie versuchen zu tun, ist das Standarddatumsformat außer Kraft setzen, sage ich selbst einige Zeit, und Affe Patch speichern. Ich habe diese auf meine Einstellungsdatei und alles scheint vortrefflich mit meinem bevorzugten Standardformat zu arbeiten:
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
In meiner Form I'me mit:
def today():
from datetime import date
return date.today().strftime("%d.%m.%Y")
when = models.DateField(u'Когда', default=today)