Django の Forms.DateField 表示にローカルの日付形式を使用するようにする

StackOverflow https://stackoverflow.com/questions/1453413

質問

オーストラリアの形式 (dd/mm/yyyy) で日付を表示するフォームを作成する簡単な方法を見つけようとしています。これが私が見つけた唯一の方法でした。より良い解決策があるはずだと思われます。

注意すべき点:

  • 日付値を dd/mm/yyyy 形式でレンダリングする新しいウィジェットを作成しました
  • 使用しようとする値のリストに検索日付形式文字列を追加する新しい日付フィールドを作成しました。

理想的な解決策は、自動的にローカライズされる日付フィールドだと思いますが、それは私にとってはうまくいきませんでした(strftimeはUnicodeフレンドリーではないようでしたが、私はあまり努力しませんでした)

何かが足りないのでしょうか?よりエレガントな解決策はありますか?これは堅牢なアプローチですか?

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()
役に立ちましたか?

解決

確かに、私はジャンゴ/パイソンのジェダイではありませんが...

あなたのアプローチは何も間違っていないと思います。きれいな読み物です。

最初のフォーム表示で日付を適切な形式でレンダリングするためだけに独自のウィジェットを作成する必要はない場合があります。ただ使用してください format のパラメータ DateInput ウィジェットを選択すればOKです。したがって、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 メカニズムは 2 つあります。

  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 によって返されたフォーム フィールドを上書きしているため、カスタマイズは完全に失われます。

あなたのアプローチはより読みやすいと思います。

他のヒント

ちょうどフォームの初期化に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']

カスタムウィジェットのもののすべてをバイパスすることができます。

ここで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

私のフォームでI'meは使用します:

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

when = models.DateField(u'Когда', default=today)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top