4

ChoiceFieldモデルで生成された選択肢を保持しながら、Djangoのデフォルトウィジェットをオーバーライドしようとしています。これが私のモデルの関連部分です:

class UserGroup(models.Model):
    icon = models.CharField(max_length=100, choices=<function call>)

そして私の形の:

class UserGroupForm(forms.ModelForm):
    icon = models.ChoiceField(widget=IconPicker)

    class Meta:
        model = UserGroup
        fields = [ 'icon', ]

ChoiceFieldこのようにのウィジェットをオーバーライドするform.fields['icon'].choicesと、通常はモデルから継承される属性が上書きされ[]、Djangoのためにに設定されます。フォームからフィールド定義を削除するiconと、選択肢は保持されますが、もちろんウィジェットのデフォルトはSelect。です。

(モデルフィールドの選択肢を生成する関数は、残念ながらフォームコードからアクセスできません。)

私がこれまでに思いついた最善の方法は、iconフォームフィールドの定義を次のように変更することです。

icon = ChoiceField(choices=UserGroup._meta.get_field_by_name('icon')[0].choices, 
                   widget=IconPicker)

しかし、これは不格好であり、内省されたChoiceField動作のように、選択肢が自動的に渡されるようにしたいと思います。(私はサブクラス化を試みChoiceFieldましIconChoiceFieldたが、デフォルトのウィジェットはですが、この問題のためにDjangoはデフォルトのウィジェットを使用してIconPickerに変換し直します。)TypedChoiceFieldSelect

モデルから 継承する動作を維持しながら、ChoiceFieldの属性をオーバーライドする方法はありますか?widgetchoices

4

2 に答える 2

7

モデルで指定した選択肢が失われる理由、つまり「設定する[]は「Djangoのため」ではなく、アイコンフィールドを線で上書きするためだと思います。icon = models.ChoiceField(widget=IconPicker)

モデルフォームを使用している場合は、initでウィジェットをオーバーライドする必要はありません。代わりに、ウィジェットはウィジェットディクショナリのMetaクラスで指定する必要があります。

class UserGroupForm(forms.ModelForm):

    class Meta:
        model = UserGroup
        fields = [ 'icon', ]
        widgets = {
            'icon': IconPicker
        }

選択肢をオーバーライドすることに関しては、単純に行うことができますがself.fields['icon'].choices = UserGroupForm.ICON_CHOICES、この場合、選択肢をオーバーライドする必要はないと思います。

于 2013-10-29T15:32:12.060 に答える
5

理解した。UserGroupForm'sで少し自己参照が必要でした__init__

def __init__(self, *args, **kwargs):
    super(UserGroupForm, self).__init__(*args, **kwargs)
    self.fields['icon'].widget = IconPicker(choices=self.fields['icon'].choices)
于 2012-06-16T10:56:59.883 に答える