Django BooleanField作为单选按钮?

Django BooleanField作为单选按钮?,django,django-models,django-forms,Django,Django Models,Django Forms,Django 1.0.2中是否有一个小部件可以将models.BooleanField呈现为两个单选按钮而不是复选框?您可以通过覆盖ModelForm中的字段定义来实现这一点: class MyModelForm(forms.ModelForm): boolfield = forms.TypedChoiceField( coerce=lambda x: x == 'True', choices=((False,

Django 1.0.2中是否有一个小部件可以将
models.BooleanField
呈现为两个单选按钮而不是复选框?

您可以通过覆盖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

还请记住,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

稍微修改一下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

下面是一个使用lambda的快速脏强制函数,它绕过了“False”->True问题:

...
boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
...
Django 1.2为modelforms添加了“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 db测试过这个问题,它也将布尔值存储为1/0值,在没有自定义强制函数的情况下,它似乎可以正常工作。

由于@Daniel Roseman answer中存在问题,bool('False')-->True,所以现在我将两个答案组合在一起,形成一个解决方案

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+

其他解决方案:

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 1.5):


在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.')             
        ])}

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
    )

它给出了一个要点按钮列表,我不知道如何使它不这样做

不幸的是,这不起作用,因为强制=bool传递的是一个字符串值,而不是布尔值和bool(“False”)=>True。因此,我必须编写一个自定义强制函数来获取字符串值并转换为bool,然后它就可以工作了。谢谢你的指针。真的应该更新,因为正如@dar所指出的,这实际上不起作用,因为
bool('False')
=>
True
。选项不应该是
('False',False),('True',True))
?换句话说,他们不应该是另一种方式吗?只是遇到了这个问题,并想注意这个答案的更新工作。Per:
TypedChoiceField(强制=lambda x:x='True',choices=((False,'No'),(True,'Yes')),widget=forms.RadioSelect)
这样,字段在form.changed_数据中显示不正确,因为在比较表单输入值和初始值时使用强制。将bool True传递给强制结果会导致False,而将表单结果传递给强制结果会导致True,因此被称为changed_数据。我用以下强制方法解决了它:强制=lambda x:((x!=“False”且x不是False)或False)这在我的编辑表单上不起作用。不会从模型中提取字段的当前值。我用了eternicode的答案,这是迄今为止最干净、最“Django”的解决方案。谢谢这太棒了。我将使用django.utils.translation import ugettext_lazy as中的
,并将
BOOL_选项
更新为:
BOOL_选项=((True,('Yes')),(False,('No'))
我认为将其本地化的额外代码会分散注意力。读者的练习;)表单中定义的选项更简单:这应该是正确的答案。验证此解决方案是否有效,但请参阅。您需要在字段上设置required=False。
boolfield
指的是什么?
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
    )