[Django]-Django BooleanField as radio buttons?

69👍

You could do this by overriding the field definition in the 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

96👍

Django 1.2 has added the “widgets” Meta option for modelforms:

In your models.py, specify the “choices” for your boolean field:

BOOL_CHOICES = ((True, 'Yes'), (False, 'No'))

class MyModel(models.Model):
    yes_or_no = models.BooleanField(choices=BOOL_CHOICES)

Then, in your forms.py, specify the RadioSelect widget for that field:

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

I’ve tested this with a SQLite db, which also stores booleans as 1/0 values, and it seems to work fine without a custom coerce function.

30👍

Modifying Daniel Roseman’s answer a bit, you could fix the bool(“False”) = True problem succinctly by just using ints instead:

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

21👍

Here’s the simplest approach I could find (I’m using Django 1.5):

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

13👍

In Django 1.6, the following worked for me:

class EmailSettingsForm(ModelForm):

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

6👍

Same as @eternicode’s answer, but without modifying the model:

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

    class Meta:
        model = MyModel
        widgets = {'boolfield': yes_no}

I think this only works in Django 1.2+

👤yprez

5👍

Here’s a quick & dirty coerce function using lambda, that gets around the “False” -> True problem:

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

5👍

As there is problem in @Daniel Roseman answer, bool(‘False’) –> True, so now i have combined two answers here to make one solution.

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

Now this will work 🙂

👤Ahsan

3👍

Also remember that MySQL uses tinyint for Boolean, so True/False are actually 1/0. I used this coerce function:

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

3👍

An other solution:

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)

2👍

update for django version 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
    )

it gives a bullet point button list, i dont know how to make it not do that

Leave a comment