Django表单过滤外键选项报错Cannot unpack non-iterable object求助
问题原因
Django的ChoiceField要求传入的choices参数必须是由(实际存储值, 页面显示文本)格式的二元组组成的列表,你的代码里直接把Categoria模型实例列表传给了choices,Django在尝试拆包每一个选项为「值+显示文本」的二元组时,拿到的是单个Categoria对象,因此抛出不可迭代的错误。
此外对于外键关联的字段,直接使用ModelChoiceField比普通ChoiceField更适配,不需要手动处理选项格式。
解决方案
方案1:使用ModelChoiceField(更推荐)
直接修改表单的__init__方法,给categoria字段的queryset赋值过滤后的分类即可,不需要重新创建字段,会自动适配外键逻辑:
class ContatoForm(forms.ModelForm): class Meta: model = Contato exclude = ('created_by',) def __init__(self, *args, **kwargs): self.user = kwargs.pop('user', None) super(ContatoForm, self).__init__(*args, **kwargs) # 直接修改原有字段的查询集,过滤当前用户创建的分类 self.fields['categoria'].queryset = Categoria.objects.filter(created_by=self.user)
该方案会自动调用Categoria的__str__方法返回的内容作为选项显示文本,主键作为实际存储值,还自带外键字段的合法性校验,无需额外处理。
方案2:手动转换为ChoiceField要求的二元组格式
如果你一定要用ChoiceField,需要手动把查询到的分类实例转换成二元组列表:
class ContatoForm(forms.ModelForm): class Meta: model = Contato exclude = ('created_by',) def __init__(self, *args, **kwargs): self.user = kwargs.pop('user', None) super(ContatoForm, self).__init__(*args, **kwargs) # 手动构造符合要求的二元组列表,第一个元素是分类主键,第二个是页面显示名称 category_choices = [(cat.id, cat.nome) for cat in Categoria.objects.filter(created_by=self.user)] self.fields['categoria'] = forms.ChoiceField(choices=category_choices)
补充:你视图里的
form_categoria = CategoriaForm缺少实例化的括号,后续使用时如果报错可以检查这里,改为form_categoria = CategoriaForm()即可,该问题不影响本次报错。
内容的提问来源于stack exchange,提问作者Gabriel Carvalho
相关产品推荐
相关产品推荐

