使Django forms.DateField显示使用本地日期格式

使Django forms.DateField显示使用本地日期格式,django,forms,strftime,datefield,Django,Forms,Strftime,Datefield,我试图找到一种简单的方法来构建以澳大利亚格式(dd/mm/yyyy)显示日期的表单。这是我能找到的唯一办法。看来应该有更好的解决办法 注意事项: 创建了一个以dd/mm/yyyy格式呈现日期值的新小部件 已创建新的日期字段,以将定位日期格式字符串前置到它尝试使用的值列表中 我想理想的解决方案应该是一个自动本地化的日期字段,但这对我不起作用(strftime似乎不支持unicode,但我没有尽力) 我错过什么了吗?有更优雅的解决方案吗?这是一种稳健的方法吗 from models import

我试图找到一种简单的方法来构建以澳大利亚格式(dd/mm/yyyy)显示日期的表单。这是我能找到的唯一办法。看来应该有更好的解决办法

注意事项:

  • 创建了一个以dd/mm/yyyy格式呈现日期值的新小部件
  • 已创建新的日期字段,以将定位日期格式字符串前置到它尝试使用的值列表中
我想理想的解决方案应该是一个自动本地化的日期字段,但这对我不起作用(strftime似乎不支持unicode,但我没有尽力)

我错过什么了吗?有更优雅的解决方案吗?这是一种稳健的方法吗

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()

当然,我不是django/python绝地,但是

我认为你的方法没有任何问题。这是一本干净的书

您可能不需要创建自己的小部件,只需在第一个表单显示中以正确的格式呈现日期。只需对
DateInput
小部件使用
format
参数,就可以了。因此,在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\u 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\u fields
,可能会引入对ModelForm子代的需求,实现
formfield\u callback=customize\u fields
作为所有表单类的新基础

我使用
formfield\u回调
机制的问题有两个:

  • 它的可读性较差,并且依赖于模型表单内部工作的知识。我在任何地方都找不到关于formfield\u回调的实际文档

  • 如果您需要在ModelForm中重新定义模型字段,可以说使该字段对于该表单的特定实例不是必需的,如下所示:

       class MyModelForm(forms.ModelForm):
           formfield_callback = customize_fields
           foo = forms.DateField(required=false)
    
           class Meta:
               model = Bar
    
    您正在覆盖customize_字段返回的表单字段,因此完全丢失自定义


  • 我认为您的方法更具可读性。

    我以前使用过这种简单的方法:只需在表单的init中设置DateField.widget的“format”属性:

        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']
    
    在我的表格中,我将使用:

    def today():
        from datetime import date
        return date.today().strftime("%d.%m.%Y")
    
    when = models.DateField(u'Когда', default=today)
    

    所有自定义小部件都可以绕过

    以下是从
    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
    
    您会注意到小部件的格式是使用format模块设置的。根据区域设置选择“格式”模块。如果您是从美国浏览,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'
    )
    
    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
    
    正如您在第一个代码块中看到的,Django选择了其中的第一个。更改格式的彻底方法是创建自己的格式模块,覆盖Django对相关区域设置的默认设置。为此,请调查。如果你所要做的就是覆盖默认的日期格式,我建议你节省一些时间和补丁。我将其添加到我的设置文件中,所有内容都以我首选的默认格式出色地工作:

    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'
    )
    
    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
    

    一个简单的替代方法是依靠javascript日历小部件进行本地化。我们使用的方法只是隐藏我的日期字段,并使用指定的本地格式创建另一个。有关特定小部件和连接小部件的任何信息?我想我应该参考stackoverflow问题:。我下面的回答提供了一种比覆盖小部件格式更为通用的方法。