Dealing with Django form data for beginners.

I have a continual interest in finding the rough edges of learning Django. Some of the points of form and request handling have been coming up for me recently. What follows is an attempt at some explanation of the difference between request.POST or request.GET and form.cleaned_data of a valid Django Form.

There are two different ways to get the info that you're looking for.

request.POST[somekey] Where somekey is a string representing the associated html <input name="somekey" />.

There is also forms.cleaned_data[somekey] where somekey is the name of the attribute on the forms.Form subclass that you've initialzed and checked the validation of earlier.

When you get it from request.POST it might not be valid, and it won't be convered into the proper python type. for example:

Consider the form:

from django import forms
class BirthDayForm(forms.Form):
    birth_month = forms.IntegerField(min_value=1, max_value=12)
    birth_day = forms.IntegerField(min_value=1, max_value=31)
    birth_year = forms.IntegerField(min_value=1900, max_value=2014)

In your view you could implement this in this way:

from .forms import BirthDayForm

def birthday_view(request):
    bday_form = BirthDayForm(request.POST or None)

    if form.is_valid():
        print bday.cleaned_data['birth_year']

    return TemplateResponse(request, 'some_template.html', {"form": bday_form})

and in your template

    <form method="POST">
         {{ form.as_p }}
         <input type="submit">
    </form>

When you get the form it will print:

        <form method="POST">
         <input type="number" name="birth_month" id="id_birth_month" />
         <input type="number" name="birth_day" id="id_birth_day" />
         <input type="number" name="birth_year" id="id_birth_year" />
         <input type="submit">
    </form>

Now if you were to put a pdb into your view like this:

from .forms import BirthDayForm

def birthday_view(request):
    bday_form = BirthDayForm(request.POST or None)

    if form.is_valid():
        import pdb; pdb.set_trace()
        print bday.cleaned_data['birth_year']

    return TemplateResponse(request, 'some_template.html', {"form": bday_form})

You would see (forgive me for not being exact, I haven't tested all this):

(pdb) type(request.POST['birth_year'])
> string
(pdb) type(form.cleaned_data['birth_year'])
> int

There are also several other complexities. You can add a "prefix" to a form, which would change the key of the request.POST dictionary, but it would NOT change the key of the cleaned_data.

consider:

from .forms import BirthDayForm

def birthday_view(request):
    #add bday prefix to the form, because later we're going to have another form on this page with the same names, because it's a quiz page about your birthday, and the birthday of several dead presidents. sort of a "which dead president are you" quiz page for buzzfeed. It's not very fun.
    bday_form = BirthDayForm(request.POST or None, prefix="bday")

    if form.is_valid():
        print bday.cleaned_data['birth_year']

    return TemplateResponse(request, 'some_template.html', {"form": bday_form})

This would render as:

        <form method="POST">
         <input type="number" name="bday-birth_month" id="id_bday_birth_month" />
         <input type="number" name="bday-birth_day" id="id_bday_birth_day" />
         <input type="number" name="bday-birth_year" id="id_bday_birth_year" />
         <input type="submit">
    </form>

You can see that it changed the name and id attributes of the rendered form.

This would mean that if you put the PDB at the exact same spot...

(pdb) type(request.POST['birth_year'])
> KeyError, request.POST has no key birth_year
(pdb) request.POST.keys()
> ["bday-birth_month", "bday-birth_day", "bday-birth_year"]

But notice that the form.cleaned_data turns the keys back into the exact same name as the fields on the BirthDayForm that we defined earlier.

(pdb) type(form.cleaned_data['birth_year'])
> int

I think we could keep expanding this BirthDayForm concept to tease out the other things are conceptually a little difficult, like the validation process, converting crappy request.POST data into good python data, validating multiple fields together (my birthday is suddenly February 30th! because your form let me do that!)


Comments and Messages

I won't ever give out your email address. I don't publish comments but if you'd like to write to me then you could use this form.

Issac Kelly