ChoiceField在使用元组时不显示空标签

44 投票
9 回答
30913 浏览
提问于 2025-04-15 16:10

我想做什么

我打算在我的数据库里保存关于比赛的数据。我希望能够根据某些条件来搜索比赛,特别是比赛类型。

关于比赛类型

比赛类型是以一个元组的形式保存的。下面是一个稍微简化的例子:

COMPETITION_TYPE_CHOICES = (
    (1, 'Olympic Games'),
    (2, 'ISU Championships'),
    (3, 'Grand Prix Series'),
)

这些在模型中是这样使用的(同样,这也是一个简化版的模型):

class Competition(models.Model):
    name = models.CharField(max_length=256)
    type = models.IntegerField(choices=COMPETITION_TYPE_CHOICES) 

搜索表单

我不想让搜索表单里的字段是必填的,所以表单是这样定义的:

class CompetitionSearchForm(forms.Form):
    name = forms.CharField(required=False)
    type = forms.ChoiceField(choices=COMPETITION_TYPE_CHOICES,required=False)

问题

我希望在选择字段的下拉框中显示一个空的标签,但我没有看到。任何帮助都会非常感谢 :)

9 个回答

10

更好的选择是在表单的初始化方法中更新字段选项。

COMPETITION_TYPE_CHOICES = (
    (1, 'Olympic Games'),
    (2, 'ISU Championships'),
    (3, 'Grand Prix Series'),
)


class CompetitionSearchForm(forms.Form):
    name = forms.CharField(required=False)
    type = forms.ChoiceField(choices=COMPETITION_TYPE_CHOICES,required=False)

    def __init__(self, *args, **kwargs):
        super(CompetitionSearchForm, self).__init__(*args, **kwargs)
        self.fields['type'].choices.insert(0, ('','---------' ) )
33

我试过Monika和Evgeniy的解决方案,但都没有成功。不过Monika提到的一个好点子是,选择项不一定要用元组来表示。因此,最简单(而且最简洁)的办法就是直接按照Django在模型字段中已经做的那样。只需要在把选择项转换成列表后,把空的选择项和其他选项合并在一起就可以了:

from django.db.models.fields import BLANK_CHOICE_DASH

...

type = forms.ChoiceField(choices=BLANK_CHOICE_DASH + list(COMPETITION_TYPE_CHOICES), required=False)
36

我找到了一种解决方案,能按照我想要的方式工作,而且没有违反DRY原则。虽然不是特别干净,但我想这也算可以了。

根据文档,choices不一定非得是一个元组:

最后要注意的是,choices可以是任何可迭代的对象——不一定是列表或元组。这让你可以动态地构建choices。不过,如果你发现自己在费劲地让choices变得动态,可能更好的办法是使用一个合适的数据库表和ForeignKey。choices是用来存放那些不太会改变的静态数据的。

所以我目前采用的解决方案是:

COMPETITION_TYPE_CHOICES = [
     (1, 'Olympic Games'),
     (2, 'ISU Championships'),
     (3, 'Grand Prix Series'),
]

COMP_TYPE_CHOICES_AND_EMPTY = [('','All')] + COMPETITION_TYPE_CHOICES

然后:

class CompetitionSearchForm(forms.Form):
    name = forms.CharField(required=False)
    type = forms.ChoiceField(choices=COMP_TYPE_CHOICES_AND_EMPTY, required=False)

模型保持不变。

撰写回答