表单 ModelChoiceField 查询集 + 额外选择字段 django 表单

Posted

技术标签:

【中文标题】表单 ModelChoiceField 查询集 + 额外选择字段 django 表单【英文标题】:forms ModelChoiceField queryset + extra choice fields django forms 【发布时间】:2011-07-13 23:08:22 【问题描述】:

我正在尝试在从查询集加载的 ModelChoiceField 中创建一个表单,我想向 ModelChoiceField 添加一些自定义值以进行扩展,我使用了选择字段,如下所示,但在更新表单时,出现以下错误

表单错误: 选择一个有效的选项。该选择不是可用的选择之一。

代码:

 self.fields['lead'] = forms.ModelChoiceField(queryset = Pepole.objects.filter(poc__in       = ('lead','sr.lead')))
 self.fields['lead2'] = forms.ModelChoiceField(queryset = Pepole.objects.filter(role__in = ('lead','sr.lead')))
      choice_field = self.fields['lead']                                    
      choice_field.choices = list(choice_field.choices) + [('None', 'None')]
      choice_field = self.fields['lead2']                                    
      choice_field.choices = list(choice_field.choices) + [('None', 'None')]

我在这里做错了吗?

【问题讨论】:

【参考方案1】:

你有一个 pk 'None' 的 Person 对象吗?

我认为你应该使用

self.fields['lead'] = forms.ModelChoiceField(queryset = Pepole.objects.filter(poc__in       = ('lead','sr.lead')), empty_label="None")
self.fields['lead2'] = forms.ModelChoiceField(queryset = Pepole.objects.filter(role__in = ('lead','sr.lead')), empty_label="None")

编辑:

由于您使用的是模型选择字段,我认为您的所有选择要么是该模型类型,要么没有。

您可以通过修改您传递给 modlechoicefield 的构造函数的查询集来“扩展”该类型的选择,例如:

qs = People.objects.filter(poc__in = ('lead','sr.lead'))
ext = People.objects.filter(role__in = ('lead', 'sr.lead'))

qs = qs | ext

self.fields['lead'] = forms.ModelChoiceField(queryset = qs, empty_label='None')
or for updating
self.fields['lead'].queryset = qs

这个问题稍微谈到了modelchoicefield,你可能会感兴趣:

How do I filter ForeignKey choices in a Django ModelForm?

【讨论】:

不,添加 empty_label="None" 后它也不起作用。这里我的问题是将选择从查询集扩展到选择选项【参考方案2】:

那是行不通的。看看ModelChoiceField 是如何工作的:

try:
    key = self.to_field_name or 'pk'
    value = self.queryset.get(**key: value)
except self.queryset.model.DoesNotExist:
    raise ValidationError(self.error_messages['invalid_choice'])
return value

你不能随意添加一些东西。

改用ChoiceField 并自定义处理数据。

class TestForm(forms.Form):
    mychoicefield = forms.ChoiceField(choices=QS_CHOICES)

    def __init__(self, *args, **kwargs):
        super(TestForm, self).__init__(*args, **kwargs)
        self.fields['mychoicefield'].choices = \
            list(self.fields['mychoicefield'].choices) + [('new stuff', 'new')]

    def clean_mychoicefield(self):
        data = self.cleaned_data.get('mychoicefield')
        if data in QS_CHOICES:
            try:
                data = MyModel.objects.get(id=data)
            except MyModel.DoesNotExist:
                raise forms.ValidationError('foo')
        return data

【讨论】:

【参考方案3】:

您似乎只想允许这些表单字段是可选的。不要让自己难受。请参阅the documentation,了解如何根据需要标记表单域。

lead = forms.ModelChoiceField(queryset=People.objects.filter(poc__in=('lead', 'sr.lead')), required=False)

【讨论】:

以上是关于表单 ModelChoiceField 查询集 + 额外选择字段 django 表单的主要内容,如果未能解决你的问题,请参考以下文章

带有modelchoicefield的Django多个表单->查询太多

如何从两个模型填充 ModelChoiceField

如何在 ModelChoiceField 中使用多个查询集?

Modelchoicefield 查询集混淆

Django:让 ModelChoiceField 在运行时评估查询集

Django ModelChoiceField:过滤查询集并将默认值设置为对象