ChoiceField在使用元组时不显示空标签
我想做什么
我打算在我的数据库里保存关于比赛的数据。我希望能够根据某些条件来搜索比赛,特别是比赛类型。
关于比赛类型
比赛类型是以一个元组的形式保存的。下面是一个稍微简化的例子:
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)
模型保持不变。