我有一个类似于以下的模型(这是一个长形式的浓缩版本):
class UserProfile(models.Model):
display_name = models.CharField()
nationality = models.ForeignKey(Nationality)
religion = models.ForeignKey(Religion)
partner_nationality = models.ManyToManyField(
Nationality,
related_name='partner_nationality',
blank=True)
partner_religion = models.ManyToManyField(
Religion,
related_name='partner_religion',
blank=True)
以下模型形式:
class UserProfilePartnerPreferencesForm(ModelForm):
partner_nationality = ModelChoiceField(
queryset=Nationality.objects.order_by('name'),
widget=CheckboxSelectMultiple,
empty_label=None,
required=False,
to_field_name='id')
class Meta:
model = UserProfile
fields = [
'partner_religion',
'partner_nationality',
]
widgets = {
'partner_religion': CheckboxSelectMultiple(),
}
这个通用观点:
class UserProfilePartnerPreferencesUpdateView(LoginRequiredMixin,
UpdateView):
model = UserProfile
form_class = UserProfilePartnerPreferencesForm
def get(self, request, *args, **kwargs):
"""
Force the PK of the object to edit to the current user's profile
"""
self.kwargs[self.pk_url_kwarg] = request.user.profile.id
return super(UserProfilePartnerPreferencesUpdateView, self).get(
request, *args, **kwargs)
def post(self, request, *args, **kwargs):
"""
Force the PK of the object to edit to the current user's profile
"""
self.kwargs[self.pk_url_kwarg] = request.user.profile.id
return super(UserProfilePartnerPreferencesUpdateView, self).post(
request, *args, **kwargs)
所以我在模型表单中所做的是:
display_name
)此表单显示正常,但我传递自定义查询集的字段将不会保存。如果我没有给出任何值,django会在尝试保存字段时'NoneType' object is not iterable
抱怨(在此示例中为partner_nationality
)。如果我给它一个有效值,它表示该值无效。
因此,在保存表单时,似乎没有正确应用我提供自定义查询集的字段。如果我注释掉自定义(例如ModelForm中的partner_nationality
),它会使用默认设置正确保存。
如何传递自定义查询集并更改模型的ManyToMany字段的窗口小部件?此外,如果有更简单的方法(例如将参数传递给widgets
dict(定义{{1}}),奖励积分。
我正在使用Django 1.11.1。
更新
当我没有选择任何选项时,完全回溯如下:
partner_religion
答案 0 :(得分:4)
在您的模型中,partner_nationality
是ManyToManyField
。因此,您应该在表单中使用ModelMultipleChoiceField
,而不是ModelChoiceField
。
class UserProfilePartnerPreferencesForm(ModelForm):
partner_nationality = ModelMultipleChoiceField(
queryset=Nationality.objects.order_by('name'),
widget=CheckboxSelectMultiple,
)
如果您在字段定义中定义窗口小部件,则不必在widgets
中设置它。
另一种方法是在__init__
方法中更改字段的属性。例如,您可以使用以下命令更改查询集:
class UserProfilePartnerPreferencesForm(ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfilePartnerPreferencesForm, self).__init__(*args, **kwargs)
self.fields['partner_nationality'].queryset = Nationality.objects.order_by('name')