Pergunta

Eu estou tentando encontrar uma maneira fácil de formas de construção que mostram datas no formato australiano (dd / mm / aaaa). Esta foi a única maneira que eu poderia encontrar para fazê-lo. Parece que deve haver uma solução melhor.

coisas a nota:

  • Criado um novo widget que torna valor de data no formato dd / mm / aaaa
  • Criado novo campo de data para preceder a string de formato de data localizar na lista de valores que ele tenta usar

Eu imagino que a solução ideal seria uma datefield que automaticamente localizada, mas que não funcionou para mim (strftime não parecem ser unicode amigável, mas eu não tentar muito difícil)

Estou faltando alguma coisa? Existe uma solução mais elegante? Será esta uma abordagem robusta?

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()
Foi útil?

Solução

Com certeza, eu não sou um django / python Jedi, mas ...

Eu não acho que haja algo de errado com a sua abordagem. É uma leitura limpa.

Você não pode precisar criar o seu próprio widget apenas para tornar a data no formato adequado na primeira exibição formulário. Basta usar o parâmetro format para o widget DateInput e você deve estar OK. Assim, em sua classe myDateField Gostaria apenas de fazer:

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)

Você pode usar formfield_callback (Veja o resposta aceita para esta pergunta parente distante), que significa:

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 = ...

Fazendo que elimina completamente a necessidade de sua classe MyDateField, mas pode apresentar - se você quiser cada classe de formulário para customize_fields chamada -. A necessidade de um descendente ModelForm, implementando formfield_callback=customize_fields como a nova base para todas as suas classes de formulário

Meu problema com a utilização do mecanismo de formfield_callback é duas vezes:

  1. É menos legível e baseia-se no conhecimento do funcionamento interno de ModelForms. Não consigo encontrar documentação real em qualquer lugar formfield_callback ...

  2. Se você precisar redefinir um campo de modelo em um ModelForm, dizer para tornar o campo não é necessário para que a instância específica do formulário, assim:

       class MyModelForm(forms.ModelForm):
           formfield_callback = customize_fields
           foo = forms.DateField(required=false)
    
           class Meta:
               model = Bar
    

    Você está substituindo o campo de formulário retornado por customize_fields, portanto, perder completamente a personalização.

Eu acho que sua abordagem é mais legível.

Outras dicas

Eu usei essa abordagem simples antes: apenas definir o atributo 'formato' do DateField.widget no início do formulário:

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

Todas as coisas widget personalizado pode ser ignorada.

Aqui está um trecho de 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

Você vai notar que o formato do widget é definido utilizando o módulo de formato. O módulo de formato é seleccionado dependendo da localidade. Se você está navegando a partir dos EUA, Django, por padrão, django.conf.formats.locale.en.formats.py select. Aqui você vai encontrar o formato padrão:

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

Como você pode ver no primeiro bloco de código, Django seleciona a primeira delas. A abordagem completa para mudar o formato é criar seu próprio módulo de formato, substituindo padrão do Django para a localidade em questão. Para isso, olhar para FORMAT_MODULE_PATH . Se tudo que você está tentando fazer é substituir o formato padrão de data, eu digo poupar algum tempo e patch de macaco. Eu adicionei isso ao meu arquivo de configurações e tudo parece estar funcionando esplendidamente com o meu formato padrão preferido:

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

Na minha forma I'me usando:

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

when = models.DateField(u'Когда', default=today)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top