جعل Django Forms.DateField عرض استخدام تنسيق التاريخ المحلي

StackOverflow https://stackoverflow.com/questions/1453413

سؤال

أحاول إيجاد طريقة سهلة لبناء النماذج التي تظهر التواريخ في التنسيق الأسترالي (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 الآلية هي طيها:

  1. إنه أقل قابلية للقراءة وتعتمد في معرفة الأعمال الداخلية في Modelforms. لا يمكنني العثور على الوثائق الفعلية على Formfield_Callback في أي مكان ...

  2. إذا كنت بحاجة إلى إعادة تعريف حقل نموذجي في 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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top