Создание форм Django. В ShowField используется локальный формат даты - PullRequest
7 голосов
/ 21 сентября 2009

Я пытаюсь найти простой способ создания форм, которые показывают даты в австралийском формате (дд / мм / гггг). Это был единственный способ найти это. Кажется, должно быть лучшее решение.

На что обратить внимание:

  • Создан новый виджет, который отображает значение даты в формате дд / мм / гггг
  • Создано новое поле даты для добавления строки формата даты поиска к списку значений, которые он пытается использовать

Я полагаю, что идеальным решением было бы поле даты, которое автоматически локализовалось, но это не сработало для меня (strftime не был дружественным к юникоду, но я не очень старался)

Я что-то упустил? Есть ли более элегантное решение? Это надежный подход?

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

Ответы [ 4 ]

10 голосов
/ 15 октября 2009

Конечно, я не джанго / питон, но ...

Не думаю, что с вашим подходом что-то не так. Это чистое чтение.

Возможно, вам не нужно создавать собственный виджет, просто чтобы отобразить дату в правильном формате при первом отображении формы. Просто используйте параметр 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, реализующем 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, следовательно, полностью теряете настройку.

Я думаю, что ваш подход более читабелен.

6 голосов
/ 12 марта 2011

Ранее я использовал этот простой подход: просто установите атрибут 'format' DateField.widget в начале формы:

    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']
2 голосов
/ 12 апреля 2014

Все пользовательские элементы виджета можно обойти.

Вот выдержка из 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 для рассматриваемой локали. Для этого загляните в 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
0 голосов
/ 07 июля 2011

В моей форме я использую:

def today():
    from datetime import date
    return date.today().strftime("%d.%m.%Y")

when = models.DateField(u'Когда', default=today)
...