58

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

4

11 回答 11

92

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 db 对此进行了测试,该数据库还将布尔值存储为 1/0 值,并且在没有自定义强制函数的情况下似乎可以正常工作。

于 2010-10-18T16:16:23.557 回答
67

您可以通过覆盖 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
于 2009-05-12T20:42:45.790 回答
30

稍微修改 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
于 2009-09-10T15:31:37.460 回答
19

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

class MyModelForm(forms.ModelForm):
    yes_no = forms.BooleanField(widget=RadioSelect(choices=[(True, 'Yes'), 
                                                            (False, 'No')]))
于 2014-07-02T05:12:33.163 回答
12

在 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.')             
        ])}
于 2014-08-19T13:27:51.350 回答
6

与@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+

于 2012-01-12T10:23:50.367 回答
5

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

...
boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
...
于 2010-05-26T21:55:51.460 回答
4

由于@Daniel Roseman 的答案存在问题,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

现在这将起作用:)

于 2011-07-20T13:42:58.890 回答
3

还要记住 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
于 2009-06-18T08:35:12.517 回答
3

另一个解决方案:

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)
于 2013-03-05T13:12:39.460 回答
2

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
    )

它给出了一个项目符号按钮列表,我不知道如何让它不这样做

于 2020-07-22T05:49:08.563 回答