Domanda

Sto cercando di trovare un modo semplice per costruire forme che mostrano le date nel formato australiano (gg / mm / aaaa). Questo era l'unico modo che ho trovato per farlo. Sembra che ci dovrebbe essere una soluzione migliore.

Cose da notare:

  • Creato un nuovo widget che rende valore di data nel formato gg / mm / aaaa
  • Creato nuovo campo data per anteporre la data stringa di localizzare formato l'elenco dei valori che tenta di utilizzare

Immagino che la soluzione ideale sarebbe un DateField che localizzata automaticamente, ma che non ha funzionato per me (strftime non sembra essere unicode cordiale, ma non ho provato molto duro)

Mi sto perdendo qualcosa? C'è una soluzione più elegante? E 'questo un approccio robusto?

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()
È stato utile?

Soluzione

Certo, io non sono un Django / Python Jedi, ma ...

Non credo che ci sia qualcosa di sbagliato con il vostro approccio. Si tratta di una lettura pulita.

Non potrebbe essere necessario creare il tuo widget solo per rendere la data nel formato corretto sul primo display modulo. Basta usare il parametro format per il widget DateInput e si dovrebbe essere OK. Quindi, nella tua classe MyDateField Vorrei solo fare:

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)

Si potrebbe utilizzare formfield_callback (Vedere la accettato risposta per questa domanda lontani parenti), che 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 = ...

In questo che elimina completamente la necessità per la classe MyDateField, ma potrebbe introdurre - se si desidera che ogni singola classe form per chiamare customize_fields -. La necessità di un discendente ModelForm, attuazione formfield_callback=customize_fields come la nuova base per tutte le classi dei form

Il mio problema con l'utilizzo del meccanismo di formfield_callback è duplice:

  1. E 'meno leggibile e si basa nella conoscenza del funzionamento interno di ModelForms. Non riesco a trovare la documentazione reale sul formfield_callback ovunque ...

  2. Se hai bisogno di ridefinire un campo modello in un ModelForm, dire a rendere il campo non richiesto per quel particolare istanza del modulo, in questo modo:

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

    si sovrascrive il campo di modulo restituito da customize_fields, quindi perdere completamente la personalizzazione.

Credo che il tuo approccio è più leggibile.

Altri suggerimenti

Ho usato questo approccio semplice prima: basta impostare l'attributo 'format' del DateField.widget nel INIT del modulo:

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

Tutte le cose widget personalizzato può essere escluso.

Ecco un estratto da 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

Si noterà che il formato del widget viene impostato utilizzando il modulo in formato. Il modulo formato viene selezionato a seconda del locale. Se si sta navigando dagli Stati Uniti, Django, per impostazione predefinita, selezionare django.conf.formats.locale.en.formats.py. Qui troverete il formato predefinito:

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

Come si può vedere nel primo blocco di codice, Django seleziona il primo di questi. L'approccio approfondito per cambiare il formato è quello di creare il proprio modulo in formato, sovrascrivendo di default di Django per il locale in questione. Per questo, guardare in FORMAT_MODULE_PATH . Se tutti si sta cercando di fare è ignorare il formato predefinito di data, dico risparmiare tempo e la patch scimmia. Ho aggiunto questo al mio file di impostazioni e tutto sembra funzionare splendidamente con il mio formato di default preferito:

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

Nella mia forma I'me utilizzando:

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

when = models.DateField(u'Когда', default=today)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top