diff --git a/docs/newforms.txt b/docs/newforms.txt index aa48d5c162..740bbf9d26 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -2,9 +2,9 @@ The newforms library ==================== -``django.newforms`` is a new replacement for ``django.forms``, the old Django -form/manipulator/validation framework. This document explains how to use this -new form library. +``django.newforms`` is Django's fantastic new form-handling library. It's a +replacement for ``django.forms``, the old form/manipulator/validation +framework. This document explains how to use this new library. Migration plan ============== @@ -103,10 +103,10 @@ fields: ``subject``, ``message``, ``sender`` and ``cc_myself``. We'll explain the different types of fields -- e.g., ``CharField`` and ``EmailField`` -- shortly. -Creating form instances ------------------------ +Creating ``Form`` instances +--------------------------- -A form instance is either **bound** or **unbound** to a set of data. +A ``Form`` instance is either **bound** or **unbound** to a set of data. * If it's **bound** to a set of data, it's capable of validating that data and rendering the form as HTML with the data displayed in the HTML. @@ -114,7 +114,7 @@ A form instance is either **bound** or **unbound** to a set of data. * If it's **unbound**, it cannot do validation (because there's no data to validate!), but it can still render the blank form as HTML. -To create an unbound form instance, simply instantiate the class:: +To create an unbound ``Form`` instance, simply instantiate the class:: >>> f = ContactForm() @@ -155,11 +155,122 @@ if you want to bind an unbound ``Form`` instance to some data, create another a ``Form`` instance has been created, you should consider its data immutable, whether it has data or not. +Using forms to validate data +---------------------------- + +The primary task of a ``Form`` object is to validate data. With a bound +``Form`` instance, call the ``is_valid()`` method to run validation and return +a boolean designating whether the data was valid:: + + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> f.is_valid() + True + +Let's try with some invalid data. In this case, ``subject`` is blank (an error, +because all fields are required by default) and ``sender`` is not a valid +e-mail address:: + + >>> data = {'subject': '', + ... 'message': 'Hi there', + ... 'sender': 'invalid e-mail address', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> f.is_valid() + False + +Access the ``Form`` attribute ``errors`` to get a dictionary of error messages:: + + >>> f.errors + {'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']} + +In this dictionary, the keys are the field names, and the values are lists of +Unicode strings representing the error messages. The error messages are stored +in lists because a field can have multiple error messages. + +You can access ``errors`` without having to call ``is_valid()`` first. The +form's data will be validated the first time either you call ``is_valid()`` or +access ``errors``. + +Behavior of unbound forms +~~~~~~~~~~~~~~~~~~~~~~~~~ + +It's meaningless to validate a form with no data, but, for the record, here's +what happens with unbound forms:: + + >>> f = ContactForm() + >>> f.is_valid() + False + >>> f.errors + {} + +Accessing "clean" data +---------------------- + +Each ``Field`` in a ``Form`` class is responsible not only for validating data, +but also for "cleaning" it -- normalizing it to a consistent format. This is a +nice feature, because it allows data for a particular field to be input in +a variety of ways, always resulting in consistent output. + +For example, ``DateField`` normalizes input into a Python ``datetime.date`` +object. Regardless of whether you pass it a string in the format +``'1994-07-15'``, a ``datetime.date`` object or a number of other formats, +``DateField`` will always normalize it to a ``datetime.date`` object as long as +it's valid. + +Once you've created a ``Form`` instance with a set of data and validated it, +you can access the clean data via the ``clean_data`` attribute of the ``Form`` +object:: + + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> f.is_valid() + True + >>> f.clean_data + {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} + +Note that any text-based field -- such as ``CharField`` or ``EmailField`` -- +always cleans the input into a Unicode string. We'll cover the encoding +implications later in this document. + +If your data does *not* validate, your ``Form`` instance will not have a +``clean_data`` attribute:: + + >>> data = {'subject': '', + ... 'message': 'Hi there', + ... 'sender': 'invalid e-mail address', + ... 'cc_myself': True} + >>> f = ContactForm(data) + >>> f.is_valid() + False + >>> f.clean_data + Traceback (most recent call last): + ... + AttributeError: 'ContactForm' object has no attribute 'clean_data' + +Behavior of unbound forms +~~~~~~~~~~~~~~~~~~~~~~~~~ + +It's meaningless to request "clean" data in a form with no data, but, for the +record, here's what happens with unbound forms:: + + >>> f = ContactForm() + >>> f.clean_data + Traceback (most recent call last): + ... + AttributeError: 'ContactForm' object has no attribute 'clean_data' + Outputting forms as HTML ------------------------ -The first thing we can do with a form is output it as HTML. To do so, instantiate -it and ``print`` it. +The second task of a ``Form`` object is to render itself as HTML. To do so, +simply ``print`` it:: >>> f = ContactForm() >>> print f @@ -357,6 +468,37 @@ example, in the ``ContactForm`` example, the fields are defined in the order ``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML output, just change the order in which those fields are listed in the class. +How errors are displayed +~~~~~~~~~~~~~~~~~~~~~~~~ + +If you render a bound ``Form`` object, the act of rendering will automatically +run the form's validation if it hasn't already happened, and the HTML output +will include the validation errors as a ``