Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I turn a Django form into a GET request string?

I want to take a ready-made form (i.e an object of a class derived from django.Forms.form with validated bound data) and urlencode it as though it were submitted with GET. Is there a built-in way?

To show why I'm asking this questino, and why I can't just call urlencode, the output from this should be "box=on".

from django import forms
from urllib import urlencode


class DemoForm(forms.Form):
    box = forms.BooleanField(required=False)

instance = DemoForm({"box": True})  # it's irrelevant how this data is supplied
instance.is_valid()
print "encoded:", urlencode(instance.cleaned_data)

In fact it's "box=True", because urlencode isn't encoding the form it's encoding the cleaned values (and believe me, BooleanField is the simplest case).

So I'm asking for a way to encode the form as though it were a GET string. A correct GET string.

like image 555
Joe Avatar asked Nov 01 '25 06:11

Joe


1 Answers

Calling urllib's urlencode on the form's cleaned_data won't work well in two cases:

  • If you are using a ModelChoiceField, the cleaned_data will contain the actual object(s), not the IDs. These will urlencode() to their string representations instead of their primary keys.
  • If you are using a field that can hold multiple values (such as MultiValueField, MultipleChoiceField or others), urlencode() will lose all but one value from that field. So {'mykey':[1,2,3]} becomes ?mykey=3 instead of ?mykey=1&mykey=2&mykey=3 the way django does it.

To deal with both of these problems, use the form's built-in urlencode function:

form = MyForm(request.POST) #or a dict or whatever
form.is_valid()
querystring = form.data.urlencode() 

Note that this is called on data, not cleaned_data. If your form changes values as part of validation, those changes won't be reflected here.

like image 99
GDorn Avatar answered Nov 02 '25 22:11

GDorn