Mark
Mark

Reputation: 2542

Django Form Checkbox Group

I have a django app that requires a large number of inputs via checkbox.

a = forms.BooleanField(required=False, initial=True)
b = forms.BooleanField(required=False, initial=True)
c = forms.BooleanField(required=False, initial=True)

But this looks messy in the template code e.g:

{% if form.data.a%}A{% endif %}
{% if form.data.a%}B{% endif %}
{% if form.data.a%}C{% endif %}

I was hoping there would be some way of doing this with a checkbox list.

But this would require me to have all the checkboxes with the same name and a different value e.g:

<input type="checkbox" name="letters" value="a" />
<input type="checkbox" name="letters" value="b" />
<input type="checkbox" name="letters" value="c" />

So in my template code I could say request.POST.getlist( “letters” )

But I cannot seem to find any info on how to set the BooleanFields to have the same name and different value.

Can you help, or is there any easier way of doing this?

Upvotes: 2

Views: 13556

Answers (2)

Luke Sneeringer
Luke Sneeringer

Reputation: 9428

Is there a reason why you're not looping over fields and printing them indiscriminately? In other words, something like:

{% for field in form %}
    {{ field }}
{% endfor %}

...which would print all the fields, in order, including your checkboxes, and would select the checkboxes which needed to be checked? That seems like by far the easiest mechanism.

If you really need to loop over just the checkboxes, it can be done, although I would warn that the mechanism I'm about to explain is undocumented and is subject to failure in some edge cases. Still, you could do something like:

{% for field in form %}
    {% if 'checkbox' in field.as_widget %}
        {{ field }}
    {% endif %}
{% endfor %}

That will loop over all the fields in the form, but only print the checkboxes. The reason the code works is because field.as_widget is the method that prints the HTML for the widget, and since the widget is an <input type="checkbox">, the string "checkbox" occurs in it (and not in most other widgets).

When you're processing the form, you shouldn't have to mess with request.POST.getlist of anything. Just instantiate the form and pass request.POST as the first positional argument, as described in the form documentation.

Upvotes: 3

manji
manji

Reputation: 47968

Look at MultipleChoiceField:

in form:

CHOICES = (
(0, 'a'),
(1, 'b'),
(2, 'c'),
)

class MyForm(forms.Form):
    letters = forms.MultipleChoiceField(
            choices=CHOICES, 
            label="...", 
            required=True/False) 

the you can use:

request.POST.getlist( “letters” ) 

or without looking at POST after you check form's validity:

 form.cleaned_data.letters   

Upvotes: 11

Related Questions