我试图理解为什么如果我在Django中覆盖ModelForm的字段,我无法为表单字段的小部件指定选择。如果我给字段选择而不是窗口小部件,它可以工作。我的理解是,如果你给一个字段做出选择,它将被传递到小部件上进行渲染。我知道我可以使用下面的前三个片段中的任何一个,但我只是想完全理解为什么这一种方法不起作用。
这是我的ModelForm代码,谢谢!
from django import forms
from models import Guest
class RSVPForm(forms.ModelForm):
class Meta:
model = Guest
def __init__(self, *args, **kwargs):
"""
Override a form's field to change the widget
"""
super(RSVPForm, self).__init__(*args, **kwargs)
# This works
self.fields['attending_ceremony'].required = True
self.fields['attending_ceremony'].widget=forms.RadioSelect(choices=Guest.CHOICES)
# This works
self.fields['attending_ceremony'].required = True
self.fields['attending_ceremony'].widget=forms.RadioSelect()
self.fields['attending_ceremony'].choices=Guest.CHOICES
# This works
self.fields['attending_ceremony'] = forms.TypedChoiceField(
required=True,
widget=forms.RadioSelect,
choices=Guest.CHOICES
)
# This doesn't - the choices aren't set (it's an empty list)
self.fields['attending_ceremony'] = forms.TypedChoiceField(
required=True,
widget=forms.RadioSelect(choices=Guest.CHOICES)
)
答案 0 :(得分:2)
我认为解释的最佳方式是遍历ChoiceField
TypeChoiceField
,class ChoiceField(Field):
widget = Select
default_error_messages = {
'invalid_choice': _(u'Select a valid choice. %(value)s is not one of the available choices.'),
}
def __init__(self, choices=(), required=True, widget=None, label=None,
initial=None, help_text=None, *args, **kwargs):
super(ChoiceField, self).__init__(required=required, widget=widget, label=label,
initial=initial, help_text=help_text, *args, **kwargs)
self.choices = choices
def _get_choices(self):
return self._choices
def _set_choices(self, value):
# Setting choices also sets the choices on the widget.
# choices can be any iterable, but we call list() on it because
# it will be consumed more than once.
self._choices = self.widget.choices = list(value)
choices = property(_get_choices, _set_choices)
的超类。
self.fields['attending_ceremony'] = forms.TypedChoiceField(
required=True,
widget=forms.RadioSelect(choices=Guest.CHOICES)
)
举个例子,
super(ChoiceField, self).__init__
self.choices=choices
设置self.widget = widget。小部件的选择仍然设置。()
将和字段的选项设置为默认_set_choices
,因为未指定(请参阅上面的{{1}})。< / LI>
醇>
希望这是有道理的。查看代码还解释了为什么您的其他示例有效。可以同时为窗口小部件和选择字段设置选项,也可以在初始化选择字段后设置窗口小部件的选项。