Django

Code

root/django/branches/sqlalchemy/docs/forms.txt

Revision 4455, 26.3 kB (checked in by rmunn, 2 years ago)

Merged revisions 4186 to 4454 from trunk.

Line 
1 ===============================
2 Forms, fields, and manipulators
3 ===============================
4
5 Forwards-compatibility note
6 ===========================
7
8 The legacy forms/manipulators system described in this document is going to be
9 replaced in the next Django release. If you're starting from scratch, we
10 strongly encourage you not to waste your time learning this. Instead, learn and
11 use the django.newforms system, which we have begun to document in the
12 `newforms documentation`_.
13
14 If you have legacy form/manipulator code, read the "Migration plan" section in
15 that document to understand how we're making the switch.
16
17 .. _newforms documentation: ../newforms/
18
19 Introduction
20 ============
21
22 Once you've got a chance to play with Django's admin interface, you'll probably
23 wonder if the fantastic form validation framework it uses is available to user
24 code. It is, and this document explains how the framework works.
25
26 We'll take a top-down approach to examining Django's form validation framework,
27 because much of the time you won't need to use the lower-level APIs. Throughout
28 this document, we'll be working with the following model, a "place" object::
29
30     from django.db import models
31
32     PLACE_TYPES = (
33         (1, 'Bar'),
34         (2, 'Restaurant'),
35         (3, 'Movie Theater'),
36         (4, 'Secret Hideout'),
37     )
38
39     class Place(models.Model):
40         name = models.CharField(maxlength=100)
41         address = models.CharField(maxlength=100, blank=True)
42         city = models.CharField(maxlength=50, blank=True)
43         state = models.USStateField()
44         zip_code = models.CharField(maxlength=5, blank=True)
45         place_type = models.IntegerField(choices=PLACE_TYPES)
46
47         class Admin:
48             pass
49
50         def __str__(self):
51             return self.name
52
53 Defining the above class is enough to create an admin interface to a ``Place``,
54 but what if you want to allow public users to submit places?
55
56 Automatic Manipulators
57 ======================
58
59 The highest-level interface for object creation and modification is the
60 **automatic Manipulator** framework. An automatic manipulator is a utility
61 class tied to a given model that "knows" how to create or modify instances of
62 that model and how to validate data for the object. Automatic Manipulators come
63 in two flavors: ``AddManipulators`` and ``ChangeManipulators``. Functionally
64 they are quite similar, but the former knows how to create new instances of the
65 model, while the latter modifies existing instances. Both types of classes are
66 automatically created when you define a new class::
67
68     >>> from mysite.myapp.models import Place
69     >>> Place.AddManipulator
70     <class 'django.models.manipulators.AddManipulator'>
71     >>> Place.ChangeManipulator
72     <class 'django.models.manipulators.ChangeManipulator'>
73
74 Using the ``AddManipulator``
75 ----------------------------
76
77 We'll start with the ``AddManipulator``.  Here's a very simple view that takes
78 POSTed data from the browser and creates a new ``Place`` object::
79
80     from django.shortcuts import render_to_response
81     from django.http import Http404, HttpResponse, HttpResponseRedirect
82     from django import forms
83     from mysite.myapp.models import Place
84
85     def naive_create_place(request):
86         """A naive approach to creating places; don't actually use this!"""
87         # Create the AddManipulator.
88         manipulator = Place.AddManipulator()
89
90         # Make a copy of the POSTed data so that do_html2python can
91         # modify it in place (request.POST is immutable).
92         new_data = request.POST.copy()
93
94         # Convert the request data (which will all be strings) into the
95         # appropriate Python types for those fields.
96         manipulator.do_html2python(new_data)
97
98         # Save the new object.
99         new_place = manipulator.save(new_data)
100
101         # It worked!
102         return HttpResponse("Place created: %s" % new_place)
103
104 The ``naive_create_place`` example works, but as you probably can tell, this
105 view has a number of problems:
106
107     * No validation of any sort is performed. If, for example, the ``name`` field
108       isn't given in ``request.POST``, the save step will cause a database error
109       because that field is required. Ugly.
110
111     * Even if you *do* perform validation, there's still no way to give that
112       information to the user in any sort of useful way.
113
114     * You'll have to separately create a form (and view) that submits to this
115       page, which is a pain and is redundant.
116
117 Let's dodge these problems momentarily to take a look at how you could create a
118 view with a form that submits to this flawed creation view::
119
120     def naive_create_place_form(request):
121         """Simplistic place form view; don't actually use anything like this!"""
122         # Create a FormWrapper object that the template can use. Ignore
123         # the last two arguments to FormWrapper for now.
124         form = forms.FormWrapper(Place.AddManipulator(), {}, {})
125         return render_to_response('places/naive_create_form.html', {'form': form})
126
127 (This view, as well as all the following ones, has the same imports as in the
128 first example above.)
129
130 The ``forms.FormWrapper`` object is a wrapper that templates can
131 easily deal with to create forms. Here's the ``naive_create_form.html``
132 template::
133
134     {% extends "base.html" %}
135
136     {% block content %}
137     <h1>Create a place:</h1>
138
139     <form method="post" action="../do_new/">
140     <p><label for="id_name">Name:</label> {{ form.name }}</p>
141     <p><label for="id_address">Address:</label> {{ form.address }}</p>
142     <p><label for="id_city">City:</label> {{ form.city }}</p>
143     <p><label for="id_state">State:</label> {{ form.state }}</p>
144     <p><label for="id_zip_code">Zip:</label> {{ form.zip_code }}</p>
145     <p><label for="id_place_type">Place type:</label> {{ form.place_type }}</p>
146     <input type="submit" />
147     </form>
148     {% endblock %}
149
150 Before we get back to the problems with these naive set of views, let's go over
151 some salient points of the above template:
152
153     * Field "widgets" are handled for you: ``{{ form.field }}`` automatically
154       creates the "right" type of widget for the form, as you can see with the
155       ``place_type`` field above.
156
157     * There isn't a way just to spit out the form. You'll still need to define
158       how the form gets laid out. This is a feature: Every form should be
159       designed differently. Django doesn't force you into any type of mold.
160       If you must use tables, use tables. If you're a semantic purist, you can
161       probably find better HTML than in the above template.
162
163     * To avoid name conflicts, the ``id`` values of form elements take the
164       form "id_*fieldname*".
165
166 By creating a creation form we've solved problem number 3 above, but we still
167 don't have any validation. Let's revise the validation issue by writing a new
168 creation view that takes validation into account::
169
170     def create_place_with_validation(request):
171         manipulator = Place.AddManipulator()
172         new_data = request.POST.copy()
173
174         # Check for validation errors
175         errors = manipulator.get_validation_errors(new_data)
176         if errors:
177             return render_to_response('places/errors.html', {'errors': errors})
178         else:
179             manipulator.do_html2python(new_data)
180             new_place = manipulator.save(new_data)
181             return HttpResponse("Place created: %s" % new_place)
182
183 In this new version, errors will be found -- ``manipulator.get_validation_errors``
184 handles all the validation for you -- and those errors can be nicely presented
185 on an error page (templated, of course)::
186
187     {% extends "base.html" %}
188
189     {% block content %}
190
191     <h1>Please go back and correct the following error{{ errors|pluralize }}:</h1>
192     <ul>
193         {% for e in errors.items %}
194         <li>Field "{{ e.0 }}": {{ e.1|join:", " }}</li>
195         {% endfor %}
196     </ul>
197
198     {% endblock %}
199
200 Still, this has its own problems:
201
202     * There's still the issue of creating a separate (redundant) view for the
203       submission form.
204
205     * Errors, though nicely presented, are on a separate page, so the user will
206       have to use the "back" button to fix errors. That's ridiculous and unusable.
207
208 The best way to deal with these issues is to collapse the two views -- the form
209 and the submission -- into a single view.  This view will be responsible for
210 creating the form, validating POSTed data, and creating the new object (if the
211 data is valid). An added bonus of this approach is that errors and the form will
212 both be available on the same page, so errors with fields can be presented in
213 context.
214
215 .. admonition:: Philosophy:
216
217     Finally, for the HTTP purists in the audience (and the authorship), this
218     nicely matches the "true" meanings of HTTP GET and HTTP POST: GET fetches
219     the form, and POST creates the new object.
220
221 Below is the finished view::
222
223     def create_place(request):
224         manipulator = Place.AddManipulator()
225
226         if request.method == 'POST':
227             # If data was POSTed, we're trying to create a new Place.
228             new_data = request.POST.copy()
229
230             # Check for errors.
231             errors = manipulator.get_validation_errors(new_data)
232
233             if not errors:
234                 # No errors. This means we can save the data!
235                 manipulator.do_html2python(new_data)
236                 new_place = manipulator.save(new_data)
237
238                 # Redirect to the object's "edit" page. Always use a redirect
239                 # after POST data, so that reloads don't accidently create
240                 # duplicate entires, and so users don't see the confusing
241                 # "Repost POST data?" alert box in their browsers.
242                 return HttpResponseRedirect("/places/edit/%i/" % new_place.id)
243         else:
244             # No POST, so we want a brand new form without any data or errors.
245             errors = new_data = {}
246
247         # Create the FormWrapper, template, context, response.
248         form = forms.FormWrapper(manipulator, new_data, errors)
249         return render_to_response('places/create_form.html', {'form': form})
250
251 and here's the ``create_form`` template::
252
253     {% extends "base.html" %}
254
255     {% block content %}
256     <h1>Create a place:</h1>
257
258     {% if form.has_errors %}
259     <h2>Please correct the following error{{ form.error_dict|pluralize }}:</h2>
260     {% endif %}
261
262     <form method="post" action=".">
263     <p>
264         <label for="id_name">Name:</label> {{ form.name }}
265         {% if form.name.errors %}*** {{ form.name.errors|join:", " }}{% endif %}
266     </p>
267     <p>
268         <label for="id_address">Address:</label> {{ form.address }}
269         {% if form.address.errors %}*** {{ form.address.errors|join:", " }}{% endif %}
270     </p>
271     <p>
272         <label for="id_city">City:</label> {{ form.city }}
273         {% if form.city.errors %}*** {{ form.city.errors|join:", " }}{% endif %}
274     </p>
275     <p>
276         <label for="id_state">State:</label> {{ form.state }}
277         {% if form.state.errors %}*** {{ form.state.errors|join:", " }}{% endif %}
278     </p>
279     <p>
280         <label for="id_zip_code">Zip:</label> {{ form.zip_code }}
281         {% if form.zip_code.errors %}*** {{ form.zip_code.errors|join:", " }}{% endif %}
282     </p>
283     <p>
284         <label for="id_place_type">Place type:</label> {{ form.place_type }}
285         {% if form.place_type.errors %}*** {{ form.place_type.errors|join:", " }}{% endif %}
286     </p>
287     <input type="submit" />
288     </form>
289     {% endblock %}
290
291 The second two arguments to ``FormWrapper`` (``new_data`` and ``errors``)
292 deserve some mention.
293
294 The first is any "default" data to be used as values for the fields. Pulling
295 the data from ``request.POST``, as is done above, makes sure that if there are
296 errors, the values the user put in aren't lost. If you try the above example,
297 you'll see this in action.
298
299 The second argument is the error list retrieved from
300 ``manipulator.get_validation_errors``.  When passed into the ``FormWrapper``,
301 this gives each field an ``errors`` item (which is a list of error messages
302 associated with the field) as well as a ``html_error_list`` item, which is a
303 ``<ul>`` of error messages. The above template uses these error items to
304 display a simple error message next to each field. The error list is saved as
305 an ``error_dict`` attribute of the ``FormWrapper`` object.
306
307 Using the ``ChangeManipulator``
308 -------------------------------
309
310 The above has covered using the ``AddManipulator`` to create a new object. What
311 about editing an existing one? It's shockingly similar to creating a new one::
312
313     def edit_place(request, place_id):
314         # Get the place in question from the database and create a
315         # ChangeManipulator at the same time.
316         try:
317             manipulator = Place.ChangeManipulator(place_id)
318         except Place.DoesNotExist:
319             raise Http404
320
321         # Grab the Place object in question for future use.
322         place = manipulator.original_object
323
324         if request.method == 'POST':
325             new_data = request.POST.copy()
326             errors = manipulator.get_validation_errors(new_data)
327             if not errors:
328                 manipulator.do_html2python(new_data)
329                 manipulator.save(new_data)
330
331                 # Do a post-after-redirect so that reload works, etc.
332                 return HttpResponseRedirect("/places/edit/%i/" % place.id)
333         else:
334             errors = {}
335             # This makes sure the form accurate represents the fields of the place.
336             new_data = manipulator.flatten_data()
337
338         form = forms.FormWrapper(manipulator, new_data, errors)
339         return render_to_response('places/edit_form.html', {'form': form, 'place': place})
340
341 The only real differences are:
342
343     * We create a ``ChangeManipulator`` instead of an ``AddManipulator``.
344       The argument to a ``ChangeManipulator`` is the ID of the object
345       to be changed. As you can see, the initializer will raise an
346       ``ObjectDoesNotExist`` exception if the ID is invalid.
347
348     * ``ChangeManipulator.original_object`` stores the instance of the
349       object being edited.
350
351     * We set ``new_data`` based upon ``flatten_data()`` from the manipulator.
352       ``flatten_data()`` takes the data from the original object under
353       manipulation, and converts it into a data dictionary that can be used
354       to populate form elements with the existing values for the object.
355
356     * The above example uses a different template, so create and edit can be
357       "skinned" differently if needed, but the form chunk itself is completely
358       identical to the one in the create form above.
359
360 The astute programmer will notice the add and create functions are nearly
361 identical and could in fact be collapsed into a single view. This is left as an
362 exercise for said programmer.
363
364 (However, the even-more-astute programmer will take heed of the note at the top
365 of this document and check out the `generic views`_ documentation if all she
366 wishes to do is this type of simple create/update.)
367
368 Custom forms and manipulators
369 =============================
370
371 All the above is fine and dandy if you just want to use the automatically
372 created manipulators. But the coolness doesn't end there: You can easily create
373 your own custom manipulators for handling custom forms.
374
375 Custom manipulators are pretty simple. Here's a manipulator that you might use
376 for a "contact" form on a website::
377
378     from django import forms
379
380     urgency_choices = (
381         (1, "Extremely urgent"),
382         (2, "Urgent"),
383         (3, "Normal"),
384         (4, "Unimportant"),
385     )
386
387     class ContactManipulator(forms.Manipulator):
388         def __init__(self):
389             self.fields = (
390                 forms.EmailField(field_name="from", is_required=True),
391                 forms.TextField(field_name="subject", length=30, maxlength=200, is_required=True),
392                 forms.SelectField(field_name="urgency", choices=urgency_choices),
393                 forms.LargeTextField(field_name="contents", is_required=True),
394             )
395
396 A certain similarity to Django's models should be apparent. The only required
397 method of a custom manipulator is ``__init__`` which must define the fields
398 present in the manipulator.  See the ``django.forms`` module for
399 all the form fields provided by Django.
400
401 You use this custom manipulator exactly as you would use an auto-generated one.
402 Here's a simple function that might drive the above form::
403
404     def contact_form(request):
405         manipulator = ContactManipulator()
406         if request.method == 'POST':
407             new_data = request.POST.copy()
408             errors = manipulator.get_validation_errors(new_data)
409             if not errors:
410                 manipulator.do_html2python(new_data)
411
412                 # Send e-mail using new_data here...
413
414                 return HttpResponseRedirect("/contact/thankyou/")
415         else:
416             errors = new_data = {}
417         form = forms.FormWrapper(manipulator, new_data, errors)
418         return render_to_response('contact_form.html', {'form': form})
419
420 ``FileField`` and ``ImageField`` special cases
421 ==============================================
422
423 Dealing with ``FileField`` and ``ImageField`` objects is a little more
424 complicated.
425
426 First, you'll need to make sure that your ``<form>`` element correctly defines
427 the ``enctype`` as ``"multipart/form-data"``, in order to upload files::
428
429   <form enctype="multipart/form-data" method="post" action="/foo/">
430
431 Next, you'll need to treat the field in the template slightly differently. A
432 ``FileField`` or ``ImageField`` is represented by *two* HTML form elements.
433
434 For example, given this field in a model::
435
436    photo = model.ImageField('/path/to/upload/location')
437
438 You'd need to display two formfields in the template::
439
440    <p><label for="id_photo">Photo:</label> {{ form.photo }}{{ form.photo_file }}</p>
441
442 The first bit (``{{ form.photo }}``) displays the currently-selected file,
443 while the second (``{{ form.photo_file }}``) actually contains the file upload
444 form field. Thus, at the validation layer you need to check the ``photo_file``
445 key.
446
447 Finally, in your view, make sure to access ``request.FILES``, rather than
448 ``request.POST``, for the uploaded files. This is necessary because
449 ``request.POST`` does not contain file-upload data.
450
451 For example, following the ``new_data`` convention, you might do something like
452 this::
453
454    new_data = request.POST.copy()
455    new_data.update(request.FILES)
456
457 Validators
458 ==========
459
460 One useful feature of manipulators is the automatic validation. Validation is
461 done using a simple validation API: A validator is a callable that raises a
462 ``ValidationError`` if there's something wrong with the data.
463 ``django.core.validators`` defines a host of validator functions (see below),
464 but defining your own couldn't be easier::
465
466     from django.core import validators
467     from django import forms
468
469     class ContactManipulator(forms.Manipulator):
470         def __init__(self):
471             self.fields = (
472                 # ... snip fields as above ...
473                 forms.EmailField(field_name="to", validator_list=[self.isValidToAddress])
474             )
475
476         def isValidToAddress(self, field_data, all_data):
477             if not field_data.endswith("@example.com"):
478                 raise validators.ValidationError("You can only send messages to example.com e-mail addresses.")
479
480 Above, we've added a "to" field to the contact form, but required that the "to"
481 address end with "@example.com" by adding the ``isValidToAddress`` validator to
482 the field's ``validator_list``.
483
484 The arguments to a validator function take a little explanation.  ``field_data``
485 is the value of the field in question, and ``all_data`` is a dictionary of all
486 the data being validated.
487
488 .. admonition:: Note::
489
490     At the point validators are called all data will still be
491     strings (as ``do_html2python`` hasn't been called yet).
492
493 Also, because consistency in user interfaces is important, we strongly urge you
494 to put punctuation at the end of your validation messages.
495
496 When are validators called?
497 ---------------------------
498
499 After a form has been submitted, Django first checks to see that all the
500 required fields are present and non-empty. For each field that passes that
501 test *and if the form submission contained data* for that field, all the
502 validators for that field are called in turn. The emphasized portion in the
503 last sentence is important: if a form field is not submitted (because it
504 contains no data -- which is normal HTML behavior), the validators are not
505 run against the field.
506
507 This feature is particularly important for models using
508 ``models.BooleanField`` or custom manipulators using things like
509 ``forms.CheckBoxField``. If the checkbox is not selected, it will not
510 contribute to the form submission.
511
512 If you would like your validator to run *always*, regardless of whether its
513 attached field contains any data, set the ``always_test`` attribute on the
514 validator function. For example::
515
516     def my_custom_validator(field_data, all_data):
517         # ...
518     my_custom_validator.always_test = True
519
520 This validator will always be executed for any field it is attached to.
521
522 Ready-made validators
523 ---------------------
524
525 Writing your own validator is not difficult, but there are some situations
526 that come up over and over again. Django comes with a number of validators
527 that can be used directly in your code. All of these functions and classes
528 reside in ``django/core/validators.py``.
529
530 The following validators should all be self-explanatory. Each one provides a
531 check for the given property:
532
533     * isAlphaNumeric
534     * isAlphaNumericURL
535     * isSlug
536     * isLowerCase
537     * isUpperCase
538     * isCommaSeparatedIntegerList
539     * isCommaSeparatedEmailList
540     * isValidIPAddress4
541     * isNotEmpty
542     * isOnlyDigits
543     * isNotOnlyDigits
544     * isInteger
545     * isOnlyLetters
546     * isValidANSIDate
547     * isValidANSITime
548     * isValidEmail
549     * isValidImage
550     * isValidImageURL
551     * isValidPhone
552     * isValidQuicktimeVideoURL
553     * isValidURL
554     * isValidHTML
555     * isWellFormedXml
556     * isWellFormedXmlFragment
557     * isExistingURL
558     * isValidUSState
559     * hasNoProfanities
560
561 There are also a group of validators that are slightly more flexible. For
562 these validators, you create a validator instance, passing in the parameters
563 described below. The returned object is a callable that can be used as a
564 validator.
565
566 For example::
567
568     from django.core import validators
569     from django import forms
570
571     power_validator = validators.IsAPowerOf(2)
572
573     class InstallationManipulator(forms.Manipulator)
574         def __init__(self):
575             self.fields = (
576                 ...
577                 forms.IntegerField(field_name = "size", validator_list=[power_validator])
578             )
579
580 Here, ``validators.IsAPowerOf(...)`` returned something that could be used as
581 a validator (in this case, a check that a number was a power of 2).
582
583 Each of the standard validators that take parameters have an optional final
584 argument (``error_message``) that is the message returned when validation
585 fails. If no message is passed in, a default message is used.
586
587 ``AlwaysMatchesOtherField``
588     Takes a field name and the current field is valid if and only if its value
589     matches the contents of the other field.
590
591 ``ValidateIfOtherFieldEquals``
592     Takes three parameters: ``other_field``, ``other_value`` and
593     ``validator_list``, in that order. If ``other_field`` has a value of
594     ``other_value``, then the validators in ``validator_list`` are all run
595     against the current field.
596
597 ``RequiredIfOtherFieldNotGiven``
598     Takes the name of the other field and this field is only required if the
599     other field has no value.
600
601 ``RequiredIfOtherFieldsNotGiven``
602     Similar to ``RequiredIfOtherFieldNotGiven``, except that it takes a list
603     of field names and if any one of the supplied fields does not have a value
604     provided, the field being validated is required.
605
606 ``RequiredIfOtherFieldEquals`` and ``RequiredIfOtherFieldDoesNotEqual``
607     Each of these validator classes takes a field name and a value (in that
608     order). If the given field does (or does not have, in the latter case) the
609     given value, then the current field being validated is required.
610
611     Note that because validators are called before any ``do_html2python()``
612     functions, the value being compared against is a string. So
613     ``RequiredIfOtherFieldEquals('choice', '1')`` is correct, whilst
614     ``RequiredIfOtherFieldEquals('choice', 1)`` will never result in the
615     equality test succeeding.
616
617 ``IsLessThanOtherField``
618     Takes a field name and validates that the current field being validated
619     has a value that is less than (or equal to) the other field's value.
620     Again, comparisons are done using strings, so be cautious about using
621     this function to compare data that should be treated as another type. The
622     string "123" is less than the string "2", for example. If you don't want
623     string comparison here, you will need to write your own validator.
624
625 ``NumberIsInRange``
626     Takes two boundary numbers, ``lower`` and ``upper``, and checks that the
627     field is greater than ``lower`` (if given) and less than ``upper`` (if
628     given). 
629    
630     Both checks are inclusive. That is, ``NumberIsInRange(10, 20)`` will allow
631     values of both 10 and 20. This validator only checks numeric values
632     (e.g., float and integer values).
633
634 ``IsAPowerOf``
635     Takes an integer argument and when called as a validator, checks that the
636     field being validated is a power of the integer.
637
638 ``IsValidFloat``
639     Takes a maximum number of digits and number of decimal places (in that
640     order) and validates whether the field is a float with less than the
641     maximum number of digits and decimal place.
642
643 ``MatchesRegularExpression``
644     Takes a regular expression (a string) as a parameter and validates the
645     field value against it.
646
647 ``AnyValidator``
648     Takes a list of validators as a parameter. At validation time, if the
649     field successfully validates against any one of the validators, it passes
650     validation. The validators are tested in the order specified in the
651     original list.
652
653 ``URLMimeTypeCheck``
654     Used to validate URL fields. Takes a list of MIME types (such as
655     ``text/plain``) at creation time. At validation time, it verifies that the
656     field is indeed a URL and then tries to retrieve the content at the URL.
657     Validation succeeds if the content could be retrieved and it has a content
658     type from the list used to create the validator.
659
660 ``RelaxNGCompact``
661     Used to validate an XML document against a Relax NG compact schema. Takes
662     a file path to the location of the schema and an optional root element
663     (which is wrapped around the XML fragment before validation, if supplied).
664     At validation time, the XML fragment is validated against the schema using
665     the executable specified in the ``JING_PATH`` setting (see the settings_
666     document for more details).
667
668 .. _`generic views`: ../generic_views/
669 .. _`models API`: ../model_api/
670 .. _settings: ../settings/
Note: See TracBrowser for help on using the browser.