[Fixed]-Django: how to change values for nullbooleanfield in a modelform?

37👍

I spent half an hour putting together a demo just to prove to myself this works:

CHOICES = (
    (None, "I do not know now"),
    (True, "Yes I acknowledge this"),
    (False, "No, I do not like this")
)

class Demo(models.Model):
    yes_no_required = models.NullBooleanField(choices = CHOICES)

class DemoForm(forms.ModelForm):
    class Meta:
        model = Demo

I looked in the Django source code. Everything can accept a choices array. Obviously, for some of those that doesn’t make sense, but it’s possible.

5👍

You can handle this in a form (withouth modifying the models) like this:

forms.NullBooleanField(
    widget=forms.RadioSelect(renderer=HorizontalRadioRendererSpace,
        choices=CHOICES),
    label='...',
    required=False)

I think it is a bad idea to use NullBooleanField for data which can be in three states like: yes/no/unset.

Editing the data works. But the big trouble arises if you want to write a search form for this data.

Then the “empty” values can have two meanings:

  • Don’t care for this attribute. Include all rows
  • Include only these rows, where the column is NULL.

The solution is simple: Use a ChoiceField.

More details here: https://github.com/guettli/programming-guidelines/blob/master/README.rst

3👍

You can modify your field widget in your ModelForm meta class:

CHOICES = (
            (None, "I do not know now"),
            (True, "Yes I acknowledge this"),
            (False, "No, I do not like this"),
           )
class DemoForm(forms.ModelForm):
    class Meta:
        model = Demo
        fields = ("demo_field",)
        widgets = {
              'demo_field': forms.RadioSelect(choices = CHOICES),
                  }

2👍

Simple approach would be to change widget choices in your form:

class YourForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(YourForm, self).__init__(*args, **kwargs)
        new_choices = ((1, 'I do not know now'),
                       (2, 'Yes I acknowledge this'),
                       (3, 'No, I do not like this'))
        self.fields['your_field'].widget.choices = new_choices

Leave a comment