Joe Jasinski
Joe Jasinski

Reputation: 10801

Python/Django BooleanField model with RadioSelect form default to empty

I'm using a Django ModelForm where my model contains a BooleanField and the form widget associated with that BooleanField is a RadioSelect widget. I'd like the the RadioSelect widget that renders to have no options selected so the user has to explicitly make a choice, but the form validation to fail if they make no selection. Is there a way to do this?

models.py

myboolean = models.BooleanField(choices=YES_NO)

forms.py

class myModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(myModelForm, self).__init__(*args, **kwargs)
        self.fields['myboolean'].widget = forms.RadioSelect(choices=YES_NO)

Upvotes: 2

Views: 14879

Answers (4)

eri
eri

Reputation: 3514

I creates custom field with default widget.

Cut of my models.py:

class Order(models.Model):
    ...
    # transport =  models.CharField(choices=transport.choices,max_length=25,null=True)
    transport = SelectField(choices=transport.choices,max_length=25,null=True)
    ...

Field definition:

from django.db import models
from django.forms import widgets

class SelectField(models.CharField):
    def formfield(self, **kwargs):
        if self._choices:
            defaults = {'widget': widgets.RadioSelect}
        defaults.update(kwargs)
        return super(SelectField, self).formfield(**defaults)

Upvotes: 0

Andrey Fedoseev
Andrey Fedoseev

Reputation: 5382

Your code actually does what you need. It renders the radio buttons with no options selected and generate the error message if nothing is selected.

A small note about your form code. I would do it like this:

class myModelForm(forms.ModelForm):

    myboolean = forms.BooleanField(widget=forms.RadioSelect(choices=YES_NO))

    class Meta:
        model = MyModel

Upvotes: 6

KeithL
KeithL

Reputation: 1150

Unfortunately, this is less of a Django issue than an HTML question. The HTML specification (RFC1866) says:

At all times, exactly one of the radio buttons in a set is checked. If none of the <INPUT> elements of a set of radio buttons specifies `CHECKED', then the user agent must check the first radio button of the set initially.

However, browsers have historically ignored this and implemented radio buttons in different ways.

HTML also makes this difficult because the "checked" attribute of the <INPUT> tag doesn't take a parameter, so you can't use a customized Django widget that sets this attribute to False or No.

A possible workaround is to put in a little Javascript that runs as part of the document's onLoad event that finds all the radio buttons on the page and sets the 'checked' attribute to false (using JQuery, for example).

Upvotes: 2

Related Questions