The preceding section covered how to determine whether the request is a GET or POST. This section covers retrieving the values that the user entered into the HTML form and validating them before saving the data to the database.
The following sections describe the process of retrieving data from the post, validating the data, handling errors, and cleaning data.
The form data can be retrieved from a POST request by accessing the POST attribute of the HttpRequest object. The POST attribute of the HttpRequest object acts like a Python dictionary, with the labels of the form fields acting as keys.
For example, suppose we're handling a POST request from an HTML form that was rendered from the following Form class:
class DataForm(forms.Form): title = forms.CharField(max_length=20) text = forms.CharField() num = forms.IntegerField()
The following code snippet from a view function would be able to access the name, text, and num fields from the POST request:
name = request.POST['name'] text = request.POST['text'] num = request.POST['num']
Using this code, the view function now has the name, text, and num values that the user entered into the form. However, that data needs to be validated. You can't trust that the user will always input proper values in the form.
Django provides the is_valid() function to verify that the values of fields in the Form object are the proper type and conform to the limits defined in the Field definitions.
The first step in validating the data that was retrieved from the POST request is to create a Form instance from the data. The following code collects the form data into a dictionary and uses that dictionary to create an instance of a BlogForm:
data = {'title': request.POST['title'], 'text': request.POST['text'], vForm = BlogForm(data)
This code creates an instance of the BlogForm class. The following code snippet uses that instance to verify whether the values in the form are valid:
if vForm.is_valid(): #Use the form data else: #Handle the invalid data
By the Way
There is a quicker way to add all the values of a POST to create an instance of the Form object. Because the POST attribute of the HttpRequest acts like a dictionary, the POST attribute itself can act as the dictionary to create an instance of the Form. For example, the following line of code creates an instance of the BlogForm from the preceding example:
vForm = BlogForm(request.POST)
Handling errors in the POST data is determined by the form's flexibility. Usually the best thing to do is report back to the user that the form has problems and ask him or her to fix the problem and resubmit.
Django provides some tools to help fix forms, as well as to let users know that the form has a problem. We covered the is_valid() function in the preceding section. The problem with is_valid() is that all it does is return a True or False answer. It doesn't actually tell you which fields have a problem.
To find out what which fields have a problem, you can access the errors attribute of the Form object. When you do so, the Form is validated, and any fields that have problems are returned as a dictionary of Field names as keys and help text strings as the values. If the Form has no errors, an empty dictionary is returned.
For example, if a Form instance called vForm has an IntegerField named num that receives the string 'one' as the value from the POST, consider the following line of code:
badFields = vForm.errors
The value of badFields would be equal to the following:
{'num', [u'Enter ca whole number']}
The dictionary returned by the errors attribute can be used in several different ways. One way is to pass the dictionary to an error-handling template that displays the invalid forms with the help text. Another way the dictionary can be used is to parse the dictionary and use a helper function in the view to add default values to the invalid fields.
Accessing clean data in the form is not really part of validation, but it definitely is worth mentioning, and there isn't a better place to do so. One of the neat things about Django Forms is that they allow you to enter data in several different formats. The Form then normalizes the data to a consistent format. Appendix B, "Django Form Field Objects," lists the normalized value that the different Form Fields use.
The best examples of this are the date and time fields. You can add dates to a DateField in the form of '1999-12-31' or '12/31/1999', but they both normalize to a Python datetime.date object.
The concept of clean data is the normalized values of data from a Form. Clean data can be accessed using a couple of methods. The cleaned_data() function of a Form instance returns a dictionary containing the Field names as keys and the normalized values as the values.
For example, consider the following code:
class DataForm(forms.Form): title = forms.CharField(max_length=20) date = forms.DateField() data = {'title': 'title', 'date':'2008-1-1'} f = DataForm(data) cleanData = f.cleaned_data
The value of cleanData would be the following dictionary:
{'date': datetime.date(2008, 1, 1), 'title': u'title'}
Watch Out!
If the form has errors, cleaned_data() raises an attribute error.
Clean data can also be accessed at the Field level by calling the clean() function of an instance of the Field class and passing in a valid value. The following code from the Django shell shows an example of using several different formats on a DateField object:
>>> fld = forms.DateField() >>> fld.clean('2008-2-2') datetime.date(2008, 2, 2) >>> fld.clean('2/3/2008') datetime.date(2008, 2, 3) >>> fld.clean('Feb 4, 2008') datetime.date(2008, 2, 4)
Try It Yourself: Retrieve and Validate the Data from a POST RequestIn the preceding "Try It Yourself" section, you modified the person_form() view function to determine if the request was a GET or POST. In this section, you will modify the POST handler to retrieve and validate the data from the POST request. Follow these steps to modify the person_form() view to create a Form instance for a Person object and validate the data from the POST against that form:
Did you Know? Did you notice the help text above the UserID field in the form? This is an added bonus of Django forms. Because the field was invalid when the instance was created, Django automatically puts in the help text. Listing 11.3. Full Contents of the person_form() view in iFriends/People/views.py
|