Added unit tests and docs for the newforms case in which the form's data doesn't include a value for a nonrequired field
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5218 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
edc014b255
commit
2c86d57284
|
@ -186,7 +186,7 @@ e-mail address::
|
||||||
>>> f.is_valid()
|
>>> f.is_valid()
|
||||||
False
|
False
|
||||||
|
|
||||||
Access the ``Form`` attribute ``errors`` to get a dictionary of error messages::
|
Access the ``errors`` attribute to get a dictionary of error messages::
|
||||||
|
|
||||||
>>> f.errors
|
>>> f.errors
|
||||||
{'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']}
|
{'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']}
|
||||||
|
@ -199,6 +199,10 @@ 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
|
form's data will be validated the first time either you call ``is_valid()`` or
|
||||||
access ``errors``.
|
access ``errors``.
|
||||||
|
|
||||||
|
The validation routines will only get called once, regardless of how many times
|
||||||
|
you access ``errors`` or call ``is_valid()``. This means that if validation has
|
||||||
|
side effects, those side effects will only be triggered once.
|
||||||
|
|
||||||
Behavior of unbound forms
|
Behavior of unbound forms
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -276,6 +280,27 @@ but ``clean_data`` contains only the form's fields::
|
||||||
>>> f.clean_data # Doesn't contain extra_field_1, etc.
|
>>> f.clean_data # Doesn't contain extra_field_1, etc.
|
||||||
{'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
|
{'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
|
||||||
|
|
||||||
|
``clean_data`` will include a key and value for *all* fields defined in the
|
||||||
|
``Form``, even if the data didn't include a value for fields that are not
|
||||||
|
required. In this example, the data dictionary doesn't include a value for the
|
||||||
|
``nick_name`` field, but ``clean_data`` includes it, with an empty value::
|
||||||
|
|
||||||
|
>>> class OptionalPersonForm(Form):
|
||||||
|
... first_name = CharField()
|
||||||
|
... last_name = CharField()
|
||||||
|
... nick_name = CharField(required=False)
|
||||||
|
>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
|
||||||
|
>>> f = OptionalPersonForm(data)
|
||||||
|
>>> f.is_valid()
|
||||||
|
True
|
||||||
|
>>> f.clean_data
|
||||||
|
{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
|
||||||
|
|
||||||
|
In this above example, the ``clean_data`` value for ``nick_name`` is set to an
|
||||||
|
empty string, because ``nick_name`` is ``CharField``, and ``CharField``s treat
|
||||||
|
empty values as an empty string. Each field type knows what its "blank" value
|
||||||
|
is -- e.g., for ``DateField``, it's ``None`` instead of the empty string.
|
||||||
|
|
||||||
Behavior of unbound forms
|
Behavior of unbound forms
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -1916,6 +1916,34 @@ True
|
||||||
>>> p.clean_data
|
>>> p.clean_data
|
||||||
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
|
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
|
||||||
|
|
||||||
|
clean_data will include a key and value for *all* fields defined in the Form,
|
||||||
|
even if the Form's data didn't include a value for fields that are not
|
||||||
|
required. In this example, the data dictionary doesn't include a value for the
|
||||||
|
"nick_name" field, but clean_data includes it. For CharFields, it's set to the
|
||||||
|
empty string.
|
||||||
|
>>> class OptionalPersonForm(Form):
|
||||||
|
... first_name = CharField()
|
||||||
|
... last_name = CharField()
|
||||||
|
... nick_name = CharField(required=False)
|
||||||
|
>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
|
||||||
|
>>> f = OptionalPersonForm(data)
|
||||||
|
>>> f.is_valid()
|
||||||
|
True
|
||||||
|
>>> f.clean_data
|
||||||
|
{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
|
||||||
|
|
||||||
|
For DateFields, it's set to None.
|
||||||
|
>>> class OptionalPersonForm(Form):
|
||||||
|
... first_name = CharField()
|
||||||
|
... last_name = CharField()
|
||||||
|
... birth_date = DateField(required=False)
|
||||||
|
>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
|
||||||
|
>>> f = OptionalPersonForm(data)
|
||||||
|
>>> f.is_valid()
|
||||||
|
True
|
||||||
|
>>> f.clean_data
|
||||||
|
{'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'}
|
||||||
|
|
||||||
"auto_id" tells the Form to add an "id" attribute to each form element.
|
"auto_id" tells the Form to add an "id" attribute to each form element.
|
||||||
If it's a string that contains '%s', Django will use that as a format string
|
If it's a string that contains '%s', Django will use that as a format string
|
||||||
into which the field's name will be inserted. It will also put a <label> around
|
into which the field's name will be inserted. It will also put a <label> around
|
||||||
|
@ -3378,7 +3406,7 @@ True
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
# MultiWidget and MultiValueField #############################################
|
# MultiWidget and MultiValueField #############################################
|
||||||
# MultiWidgets are widgets composed of other widgets. They are usually
|
# MultiWidgets are widgets composed of other widgets. They are usually
|
||||||
# combined with MultiValueFields - a field that is composed of other fields.
|
# combined with MultiValueFields - a field that is composed of other fields.
|
||||||
# MulitWidgets can themselved be composed of other MultiWidgets.
|
# MulitWidgets can themselved be composed of other MultiWidgets.
|
||||||
# SplitDateTimeWidget is one example of a MultiWidget.
|
# SplitDateTimeWidget is one example of a MultiWidget.
|
||||||
|
@ -3386,7 +3414,7 @@ True
|
||||||
>>> class ComplexMultiWidget(MultiWidget):
|
>>> class ComplexMultiWidget(MultiWidget):
|
||||||
... def __init__(self, attrs=None):
|
... def __init__(self, attrs=None):
|
||||||
... widgets = (
|
... widgets = (
|
||||||
... TextInput(),
|
... TextInput(),
|
||||||
... SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
|
... SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
|
||||||
... SplitDateTimeWidget(),
|
... SplitDateTimeWidget(),
|
||||||
... )
|
... )
|
||||||
|
@ -3411,13 +3439,13 @@ True
|
||||||
<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />
|
<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />
|
||||||
|
|
||||||
>>> class ComplexField(MultiValueField):
|
>>> class ComplexField(MultiValueField):
|
||||||
... def __init__(self, required=True, widget=None, label=None, initial=None):
|
... def __init__(self, required=True, widget=None, label=None, initial=None):
|
||||||
... fields = (
|
... fields = (
|
||||||
... CharField(),
|
... CharField(),
|
||||||
... MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
|
... MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
|
||||||
... SplitDateTimeField()
|
... SplitDateTimeField()
|
||||||
... )
|
... )
|
||||||
... super(ComplexField, self).__init__(fields, required, widget, label, initial)
|
... super(ComplexField, self).__init__(fields, required, widget, label, initial)
|
||||||
...
|
...
|
||||||
... def compress(self, data_list):
|
... def compress(self, data_list):
|
||||||
... if data_list:
|
... if data_list:
|
||||||
|
|
Loading…
Reference in New Issue