Django的BooleanField作为单选button?

Django 1.0.2中是否有一个小部件将一个models.BooleanField渲染为两个单选button而不是checkbox?

您可以通过覆盖ModelForm中的字段定义来做到这一点:

 class MyModelForm(forms.ModelForm): boolfield = forms.TypedChoiceField( coerce=lambda x: x == 'True', choices=((False, 'False'), (True, 'True')), widget=forms.RadioSelect ) class Meta: model = MyModel 

Django 1.2为模型添加了“widgets”Meta选项:

在您的models.py中,为您的布尔字段指定“选项”:

 BOOL_CHOICES = ((True, 'Yes'), (False, 'No')) class MyModel(models.Model): yes_or_no = models.BooleanField(choices=BOOL_CHOICES) 

然后,在你的forms.py中,为该字段指定RadioSelect小部件:

 class MyModelForm(forms.ModelForm): class Meta: model = MyModel widgets = { 'yes_or_no': forms.RadioSelect } 

我已经用SQLite数据库testing了这个,它也将布尔值存储为1/0的值,而且它似乎没有自定义强制函数就可以正常工作。

稍微修改Daniel Roseman的答案,你可以简单地用int来简单地修正bool(“False”)= True问题:

 class MyModelForm(forms.ModelForm): boolfield = forms.TypedChoiceField(coerce=lambda x: bool(int(x)), choices=((0, 'False'), (1, 'True')), widget=forms.RadioSelect ) class Meta: model = MyModel 

在Django 1.6中,以下工作适用于我:

 class EmailSettingsForm(ModelForm): class Meta: model = EmailSetting fields = ['setting'] widgets = {'setting': RadioSelect(choices=[ (True, 'Keep updated with emails.'), (False, 'No, don\'t email me.') ])} 

这是一个使用lambda的快速肮脏的强制函数,解决了“False” – > True问题:

 ... boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'), ... 

这是我能find的最简单的方法(我使用的是Django 1.5):

 class MyModelForm(forms.ModelForm): yes_no = forms.BooleanField(widget=RadioSelect(choices=[(True, 'Yes'), (False, 'No')])) 

还要记住MySQL使用tinyint作为布尔值,所以True / False实际上是1/0。 我用这个胁迫函数:

 def boolean_coerce(value): # value is received as a unicode string if str(value).lower() in ( '1', 'true' ): return True elif str(value).lower() in ( '0', 'false' ): return False return None 

由于在丹尼尔·罗斯曼答案有问题,布尔('假') – >真,所以现在我已经在这里合并了两个答案来作出一个解决scheme。

 def boolean_coerce(value): # value is received as a unicode string if str(value).lower() in ( '1', 'true' ): return True elif str(value).lower() in ( '0', 'false' ): return False return None class MyModelForm(forms.ModelForm): boolfield = forms.TypedChoiceField(coerce= boolean_coerce, choices=((False, 'False'), (True, 'True')), widget=forms.RadioSelect ) class Meta: model = MyModel 

现在这将工作:)

和@ eternicode的答案一样,但是没有修改模型:

 class MyModelForm(forms.ModelForm): yes_no = forms.RadioSelect(choices=[(True, 'Yes'), (False, 'No')]) class Meta: model = MyModel widgets = {'boolfield': yes_no} 

我认为这只适用于Django 1.2+

另一个解决scheme:

 from django import forms from django.utils.translation import ugettext_lazy as _ def RadioBoolean(*args, **kwargs): kwargs.update({ 'widget': forms.RadioSelect, 'choices': [ ('1', _('yes')), ('0', _('no')), ], 'coerce': lambda x: bool(int(x)) if x.isdigit() else False, }) return forms.TypedChoiceField(*args, **kwargs)