根据模型数据为ChoiceField添加一个“空”选项

3 投票
2 回答
5025 浏览
提问于 2025-04-15 14:21

我正在根据模型的数据定义一个选择字段。

field = forms.ChoiceField(choices=[[r.id, r.name] for r in Model.objects.all()])

不过,我想在选项前面加一个空选项,以便选择“没有”对象。但我找不到一个好的方法来添加这个空选项。

我尝试过的所有方法,比如:

field = forms.ChoiceField(choices=[[0, '----------']].extend([[r.id, r.name] for r in Model.objects.all()]))

都让我遇到了“NoneType对象不可迭代”的错误。到目前为止,我找到的唯一解决办法是:

def append_empty(choices):
    ret = [[0, '----------']]
    for c in choices:
        ret.append(c)
   return ret

然后当我定义我的字段时:

forms.ChoiceField(choices=append_empty([[r.id, r.name] for r in
    Restaurant.objects.all()]), required=False)

不过,我想保持代码的整洁,不想让代码变得那么糟糕。你有没有什么好主意?:p 提前谢谢你。

2 个回答

1

因为这个问题和它的答案几乎解决了我刚遇到的问题,所以我想补充一点。对我来说,id必须是空的,因为模型不把'0'当作一个有效的选项,但它接受空值(null=True, blank=True)。在初始化的时候:

self.fields['option_field'].choices = [
    ('', '------')] + [[r.id, r.name] for r in Model.objects.all()] 
10

一个简单的解决办法是这样做:

field = forms.ChoiceField(choices=[[0, '----------']] + [[r.id, r.name] for r in Model.objects.all()])

不过,你的方法有点问题。即使你的方法看起来能用,字段选项是在表单定义的时候就已经确定了,而不是在实例化的时候。所以如果你在模型表中添加了新元素,它们不会出现在选项列表里。

你可以通过在表单的 __init__ 方法中进行分配来避免这个问题。

不过,还有一个更简单的方法。与其动态地调整字段选项,不如使用一个专门用来从模型中提供选项的字段——ModelChoiceField。这个字段不仅在实例化时能动态获取模型元素的列表,而且默认情况下已经包含了一个空选项。你可以查看 文档了解更多信息。

撰写回答