【发布时间】:2010-10-25 16:14:51
【问题描述】:
在 Django 1.0.2 中是否有一个小部件可以将 models.BooleanField 呈现为两个单选按钮而不是一个复选框?
【问题讨论】:
标签: django django-models django-forms
在 Django 1.0.2 中是否有一个小部件可以将 models.BooleanField 呈现为两个单选按钮而不是一个复选框?
【问题讨论】:
标签: django django-models django-forms
Django 1.2 为模型表单添加了“widgets”元选项:
在您的 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 数据库对此进行了测试,该数据库还将布尔值存储为 1/0 值,并且在没有自定义强制函数的情况下似乎可以正常工作。
【讨论】:
from django.utils.translation import ugettext_lazy as _ 并将BOOL_CHOICES 更新为:BOOL_CHOICES = ((True, _('Yes')), (False, _('No'))) 来允许本地化版本的“是”和“否”
您可以通过覆盖 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
【讨论】:
bool('False') => True。
(('False', False), ('True', True))吗?换句话说,他们不应该反过来吗?
TypedChoiceField(coerce=lambda x: x =='True', choices=((False, 'No'), (True, 'Yes')), widget=forms.RadioSelect)
稍微修改 Daniel Roseman 的答案,您可以通过使用 ints 来简洁地解决 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.5):
class MyModelForm(forms.ModelForm):
yes_no = forms.BooleanField(widget=RadioSelect(choices=[(True, 'Yes'),
(False, 'No')]))
【讨论】:
在 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.')
])}
【讨论】:
与@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+
【讨论】:
boolfield 指的是什么?
这是一个使用 lambda 的快速而肮脏的强制函数,它解决了 "False" -> True 问题:
...
boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
...
【讨论】:
由于@Daniel Roseman 的答案存在问题,bool('False') --> 是的,所以现在我在这里将两个答案合并为一个解决方案。
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
现在这将起作用:)
【讨论】:
还要记住 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
【讨论】:
另一种解决方案:
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)
【讨论】:
django 3.0 版更新:
BOOLEAN_CHOICES = (('1', 'True label'), ('0', 'False label'))
# Filtering fields
True_or_false_question = forms.ChoiceField(
label="Some Label3",
# uses items in BOOLEAN_CHOICES
choices = BOOLEAN_CHOICES,
widget = forms.RadioSelect
)
它给出了一个要点按钮列表,我不知道如何让它不这样做
【讨论】:
list-style-type: none; 为