جعل Django Forms.DateField عرض استخدام تنسيق التاريخ المحلي
سؤال
أحاول إيجاد طريقة سهلة لبناء النماذج التي تظهر التواريخ في التنسيق الأسترالي (DD / MM / YYYY). كانت هذه هي الطريقة الوحيدة التي يمكنني العثور عليها للقيام بذلك. يبدو أن هناك حلا أفضل.
أشياء يجب ملاحظتها:
- أنشأت أداة جديدة تجعل قيمة التاريخ بتنسيق DD / MM / YYYY
- تم إنشاء حقل تاريخ جديد لإعداد سلسلة تنسيق تاريخ تحديد الموقع إلى قائمة القيم التي يحاول استخدامها
أتصور الحل المثالي سيكون علامة deafield التي تم تجميعها تلقائيا ولكنها لم تنجح بالنسبة لي (لا يبدو أن الوعاء ودود يونيكود لكنني لم أحاول صعبة للغاية)
هل فاتني شيء؟ هل هناك حل أكثر أناقة؟ هل هذا نهج قوي؟
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()
المحلول
منحت، أنا لست جانغو / بيثون جدي، ولكن ...
لا أعتقد أن هناك أي شيء خاطئ في نهجك. انها قراءة نظيفة.
قد لا تحتاج إلى إنشاء القطعة الخاصة بك فقط لتقديم التاريخ في التنسيق المناسب في عرض النموذج الأول. مجرد استخدام format
المعلمة ل DateInput
القطعة ويجب أن تكون على ما يرام. لذلك في فئة MyDateField الخاصة بك أود القيام به فقط:
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)
يمكنك استخدام formfield_callback
(انظر إجابة مقبولة لهذا السؤال المرتبط بعيد المنال)، يعني:
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 = ...
القيام بذلك تماما يلغي الحاجة الخاصة بك MyDateField
فئة، ولكن قد نقدم - إذا كنت تريد كل فئة نموذج واحدة للاتصال customize_fields
- الحاجة إلى modelform dendentendent، التنفيذ formfield_callback=customize_fields
كقاعدة جديدة لجميع فئات النماذج الخاصة بك.
مشكلتي مع استخدام formfield_callback
الآلية هي طيها:
إنه أقل قابلية للقراءة وتعتمد في معرفة الأعمال الداخلية في Modelforms. لا يمكنني العثور على الوثائق الفعلية على Formfield_Callback في أي مكان ...
إذا كنت بحاجة إلى إعادة تعريف حقل نموذجي في Modelform، فقل لجعل الحقل غير مطلوب لهذا المثال بالذات من النموذج، مثل ذلك:
class MyModelForm(forms.ModelForm): formfield_callback = customize_fields foo = forms.DateField(required=false) class Meta: model = Bar
أنت تقوم بالكتابة فوق حقل النموذج الذي تم إرجاعه بواسطة Customize_Fields، وبالتالي فقدان التخصيص تماما.
أعتقد أن نهجك هو أكثر قابلية للقراءة.
نصائح أخرى
لقد استخدمت هذا النهج البسيط من قبل: فقط قم بتعيين سمة "تنسيق" لسمة DateField.Widget في INTION للنموذج:
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']
جميع الاشياء القطعة المخصصة يمكن تجاوزها.
هنا مقتطف من 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
ستلاحظ أن تنسيق عنصر القطعة يتم تعيينه باستخدام وحدة التنسيق. يتم تحديد وحدة التنسيق اعتمادا على اللغة. إذا كنت تتصفح من الولايات المتحدة، فستحقق Django، افتراضيا، حدد django.conf.formats.locale.en.formats.py
. وبعد ستجد هنا التنسيق الافتراضي:
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'
)
كما ترون في كتلة التعليمات البرمجية الأولى، يختار Django الأول من هذه. النهج الشامل لتغيير التنسيق هو إنشاء وحدة النمطية الخاصة بك، وتجاوز الافتراضي DJango ل LOKALE المعني. لذلك، انظر إلى format_module_path.. وبعد إذا كان كل ما تحاول القيام به هو تجاوز تنسيق التاريخ الافتراضي، أقول إنقاذ نفسك بعض الوقت والقرد التصحيح. أضفت هذا إلى ملف الإعدادات الخاص بي ويبدو أن كل شيء يعمل بشكل رائع بالتنسيق الافتراضي المفضل لدي:
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
في النموذج الخاص بي أنا باستخدام:
def today():
from datetime import date
return date.today().strftime("%d.%m.%Y")
when = models.DateField(u'Когда', default=today)