Question

Je suis en train de trouver un moyen facile de construire des formes qui montrent les dates dans le format australien (jj / mm / aaaa). Ce fut la seule façon que je pouvais trouver de le faire. Il semble qu'il devrait y avoir une meilleure solution.

Les choses à noter:

  • créé un nouveau widget qui rend la valeur de date au format jj / mm / aaaa
  • Créé nouveau champ de date à préfixer la chaîne de format de date à localiser la liste des valeurs qu'il tente d'utiliser

J'imagine que la solution idéale serait une datefield qui localise automatiquement, mais cela ne fonctionne pas pour moi (strftime ne semble pas être unicode amical, mais je ne l'ai pas essayé très dur)

Est-ce que je manque quelque chose? Y at-il une solution plus élégante? Est-ce une approche solide?

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()
Était-ce utile?

La solution

D'accord, je ne suis pas un Jedi django / python, mais ...

Je ne pense pas qu'il y ait quelque chose de mal avec votre approche. Il est une lecture propre.

Vous pourriez ne pas avoir besoin de créer votre propre widget juste pour rendre la date dans le format approprié sur le premier affichage de forme. Il suffit d'utiliser le paramètre format pour le widget DateInput et vous devriez être OK. Donc, dans votre classe MyDateField Je voudrais juste faire:

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)

Vous pouvez utiliser formfield_callback (Voir accepté réponse à cette question liée lointainement), ce qui signifie:

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

Faire qui élimine complètement le besoin de votre classe MyDateField, mais pourrait présenter - si vous voulez chaque classe de formulaire pour appeler customize_fields -. La nécessité d'un descendant de ModelForm, la mise en œuvre formfield_callback=customize_fields comme la nouvelle base pour toutes les classes de formulaire

Mon problème avec l'utilisation du mécanisme de formfield_callback est double:

  1. Il est moins lisible et repose dans la connaissance du fonctionnement interne de ModelForms. Je ne peux pas trouver de la documentation sur formfield_callback réelle partout ...

  2. Si vous avez besoin de redéfinir un champ de modèle dans un ModelForm, dire rendre le champ non nécessaire pour ce cas particulier de la forme, comme suit:

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

    vous écrasez le champ de formulaire retourné par customize_fields, perdant ainsi complètement la personnalisation.

Je pense que votre approche est plus lisible.

Autres conseils

Je l'ai utilisé cette approche simple avant: il suffit de définir l'attribut « format » de la DateField.widget dans le Init du formulaire:

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

Toutes les choses widget personnalisé peut être contournée.

Voici un extrait 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

Vous remarquerez que le format du widget est défini à l'aide du module de format. Le module de format est sélectionné en fonction des paramètres régionaux. Si vous naviguez sur des États-Unis, Django, par défaut, sélectionnez django.conf.formats.locale.en.formats.py. Vous trouverez ici le format par défaut:

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

Comme vous pouvez le voir dans le premier bloc de code, Django sélectionne la première de ces derniers. L'approche en profondeur pour changer le format est de créer votre propre module de format, remplaçant par défaut de Django pour les paramètres régionaux en question. Pour cela, regarder dans FORMAT_MODULE_PATH . Si tout ce que vous essayez de faire est remplacer le format de date par défaut, je dis vous épargner un temps et un patch de singe. J'ai ajouté à mon fichier de paramètres et tout semble fonctionner à merveille avec mon format préféré par défaut:

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

Dans ma forme I'me en utilisant:

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

when = models.DateField(u'Когда', default=today)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top