Darwin Tech
Darwin Tech

Reputation: 18919

Django Forms - getting data from multiple choice fields

I have a form like so:

class MyForm(forms.Form):
    site = forms.ChoiceField(choices=SITE_CHOICES, label=ugettext_lazy('Site'),)  
    ...
    params = forms.MultipleChoiceField(
             choices=PARAM_CHOICES,
             label=ugettext_lazy('Select Parameters'),
             widget=forms.CheckboxSelectMultiple()
             )

And in my template:

<form action="{% url results %}" method="get">{% csrf_token %}
{% for field in myform %}
<div class="field_wrapper">
    {{ field.errors }}
    {{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<input type="submit" name="submit" value="{% trans 'Query' %}"  />
</form>

My problem is that when I submit the form as GET the variables are like the following:

    site=1&params=foo&params=bar&params=something&submit=Query

my params variable is clearly being overwritten by the last choice? How can get access to the submitted data as separate variables?

Any help appreciated.

Upvotes: 10

Views: 11875

Answers (3)

satels
satels

Reputation: 779

Use form.is_valid() and form.cleaned_data['params'].

Upvotes: 0

satels
satels

Reputation: 779

And use {% csrf_token %} in get request is a bad practice.

Upvotes: 2

Thomas Orozco
Thomas Orozco

Reputation: 55199

Using Django forms

You should be using Django's form handling with a POST which would majke things easier. Here goes:

if request.method == 'GET':
    form = MyFormClass()
else:
    form = MyFormClass(request.POST)
    if form.is_valid():
        do_something_with(form.cleaned_data['params'])
        return redirect('somewhere')
return render_to_response('my_template.html', RequestContext(request, {'form':form}))

Notes on using GET vs POST with forms

It's useless to include {% csrf_token %} if you're going to GET the form (Absolutely no csrf validation is done with GET requests, which make sense, as GET requests are supposed to be non-data-altering.

Anyway, if you're really going to GET the page, you can still use the same logic as written before, with a little tuning:

form = MyFormClass(request.GET)
if form.is_valid():
    do_something_with(form.cleaned_data['params'])
    return render_to_response('some_template.html', {'stuff':some_stuff})
return render_to_response('form_submission_page.html', {'form':form})

Last thing, using GET to submit data is usually bad practice, unless you're creating some search function or altering display (pagination & all).

Using request.GET

Now, if for some reason you don't want to use Django forms, you can still get around the problem and retrieve your params, you simply need to use the QueryDict.getlist instead of using the QueryDict.get method.

Here goes:

my_data = request.GET.getlist('params')

Documentation

Don't forget to check out the Django documentation on QueryDicts and on forms

Upvotes: 11

Related Questions