Frage

Ich versuche, eine einfache Möglichkeit zu finden, Formen zu bauen, die Termine im australischen Format anzeigen (dd / mm / jjjj). Dies war die einzige Art, wie ich es tun finden. Es scheint, wie es sollte eine bessere Lösung.

Dinge zu beachten:

  • ein neues Widget Erstellt der Datumswert in
  • tt / mm / jjjj Format rendert
  • neues Datumsfeld Erstellt das orten Datumsformat-Zeichenfolge in die Liste der Werte vorangestellt wird, es zu benutzen versucht,

Ich stelle mir die ideale Lösung ein Datefield sein würde, die automatisch lokalisiert, aber das funktionierte nicht für mich arbeiten (strftime nicht Unicode zu sein schien freundlich, aber ich versuche, nicht sehr hart)

Bin ich etwas fehlt? Gibt es eine elegantere Lösung? Ist das ein robusterer Ansatz?

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()
War es hilfreich?

Lösung

Zugegeben, ich bin kein django / Python Jedi, aber ...

Ich glaube nicht, dass es etwas falsch mit Ihrem Ansatz. Es ist eine saubere lesen.

Sie benötigen kein eigenes Widget zu erstellen, das Datum im richtigen Format auf der ersten Form Anzeige zu machen. Verwenden Sie einfach die format Parameter für die DateInput Widget und Sie sollten in Ordnung sein. Ich würde also in Ihrer MyDateField Klasse gerade tun:

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)

könnten Sie verwenden formfield_callback (Siehe akzeptierte Antwort für diese weitläufig verwandt Frage), was bedeutet:

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

Dadurch, dass vollständig die Notwendigkeit für Ihre MyDateField Klasse beseitigt, aber vorstellen könnte - wenn man jede einzelne Formularklasse will customize_fields nennen -. Die Notwendigkeit eine Modelform Nachkommen, formfield_callback=customize_fields als neue Basis der Umsetzung für alle Formularklassen

Mein Problem des formfield_callback Mechanismus bei der Verwendung ist zweifach:

  1. Es ist weniger lesbar und verlässt sich in Kenntnis der inneren Abläufe ModelForms. Ich kann nicht unbedingt der Dokumentation auf formfield_callback finden überall ...

  2. Wenn Sie jemals ein Modellfeld in einer Modelform neu zu definieren müssen, sagen, um das Feld zu machen nicht für diese bestimmte Instanz des Formulars erforderlich, etwa so:

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

    Sie überschreiben das Formularfeld durch customize_fields zurückgegeben, daher vollständig die Anpassung zu verlieren.

Ich denke, Ihr Ansatz ist besser lesbar.

Andere Tipps

Ich habe diesen einfachen Ansatz vor: nur das ‚Format‘ Attribut des DateField.widget im init des Formulars:

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

Alle benutzerdefinierten Widget Sachen können umgangen werden.

Hier ist ein Auszug aus 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

Sie werden bemerken, dass das Format des Widgets festgelegt wird, um das Format-Modul. Das Format-Modul wird in Abhängigkeit von dem Lokalisierungs ausgewählt. Wenn Sie aus den USA surfen, Django, die standardmäßig wählen django.conf.formats.locale.en.formats.py. Hier finden Sie das Standardformat finden:

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

Wie Sie in dem ersten Codeblock sehen, wählt Django die ersten davon. Der gründliche Ansatz um das Format zu ändern, ist ein eigenes Format Modul zu erstellen, für das Gebietsschema in Frage Djangos Standard zu überschreiben. Dazu schauen Sie in FORMAT_MODULE_PATH . Wenn alle Sie versuchen zu tun, ist das Standarddatumsformat außer Kraft setzen, sage ich selbst einige Zeit, und Affe Patch speichern. Ich habe diese auf meine Einstellungsdatei und alles scheint vortrefflich mit meinem bevorzugten Standardformat zu arbeiten:

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

In meiner Form I'me mit:

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

when = models.DateField(u'Когда', default=today)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top