diff options
| author | Adrian Holovaty <adrian@holovaty.com> | 2006-11-27 04:49:26 +0000 |
|---|---|---|
| committer | Adrian Holovaty <adrian@holovaty.com> | 2006-11-27 04:49:26 +0000 |
| commit | 49236b95e904dbf8560cfb64eb4f5c430ec8f30a (patch) | |
| tree | f72d7912194c788f72b1737d6446e828458e2707 | |
| parent | 6d36d97cb8d0c982d7481e7d439c9848ded46a77 (diff) | |
newforms: Added Form.non_field_errors() and added more examples/documentation to the unit tests
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4119 bcc190cf-cafb-0310-a4f2-bffc1f526a37
| -rw-r--r-- | django/newforms/forms.py | 11 | ||||
| -rw-r--r-- | tests/regressiontests/forms/tests.py | 66 |
2 files changed, 75 insertions, 2 deletions
diff --git a/django/newforms/forms.py b/django/newforms/forms.py index a07df84e54..667ae0a472 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -99,6 +99,13 @@ class Form(object): output.append(line) return u'\n'.join(output) + def non_field_errors(self): + """ + Returns a list of errors that aren't associated with a particular + field -- i.e., from Form.clean(). + """ + return self.errors.get(NON_FIELD_ERRORS, []) + def full_clean(self): """ Cleans all of self.data and populates self.__errors and self.clean_data. @@ -129,7 +136,9 @@ class Form(object): def clean(self): """ Hook for doing any extra form-wide cleaning after Field.clean() been - called on every field. + called on every field. Any ValidationError raised by this method will + not be associated with a particular field; it will have a special-case + association with the field named '__all__'. """ return self.clean_data diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index 8de27dee51..c7e222c7d2 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -1520,7 +1520,7 @@ A Form's fields are displayed in the same order in which they were defined. <tr><td>Field13:</td><td><input type="text" name="field13" /></td></tr> <tr><td>Field14:</td><td><input type="text" name="field14" /></td></tr> -# Sample form processing (as if in a view) #################################### +# Basic form processing in a view ############################################# >>> from django.template import Template, Context >>> class UserRegistration(Form): @@ -1568,6 +1568,70 @@ Case 2: POST with erroneous data (a redisplayed form, with errors). Case 3: POST with valid data (the success message). >>> print my_function('POST', {'username': 'adrian', 'password1': 'secret', 'password2': 'secret'}) VALID + +# Some ideas for using templates with forms ################################### + +>>> class UserRegistration(Form): +... username = CharField(max_length=10) +... password1 = CharField(widget=PasswordInput) +... password2 = CharField(widget=PasswordInput) +... def clean(self): +... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: +... raise ValidationError(u'Please make sure your passwords match.') +... return self.clean_data + +You have full flexibility in displaying form fields in a template. Just pass a +Form instance to the template, and use "dot" access to refer to individual +fields. Note, however, that this flexibility comes with the responsibility of +displaying all the errors, including any that might not be associated with a +particular field. +>>> t = Template('''<form action=""> +... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> +... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> +... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> +... <input type="submit" /> +... </form>''') +>>> print t.render(Context({'form': UserRegistration()})) +<form action=""> +<p><label>Your username: <input type="text" name="username" /></label></p> +<p><label>Password: <input type="password" name="password1" /></label></p> +<p><label>Password (again): <input type="password" name="password2" /></label></p> +<input type="submit" /> +</form> +>>> print t.render(Context({'form': UserRegistration({'username': 'django'})})) +<form action=""> +<p><label>Your username: <input type="text" name="username" value="django" /></label></p> +<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password: <input type="password" name="password1" /></label></p> +<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password (again): <input type="password" name="password2" /></label></p> +<input type="submit" /> +</form> + +To display the errors that aren't associated with a particular field -- e.g., +the errors caused by Form.clean() -- use {{ form.non_field_errors }} in the +template. If used on its own, it is displayed as a <ul> (or an empty string, if +the list of errors is empty). You can also use it in {% if %} statements. +>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'})})) +<form action=""> +<p><label>Your username: <input type="text" name="username" value="django" /></label></p> +<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> +<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> +<input type="submit" /> +</form> +>>> t = Template('''<form action=""> +... {{ form.non_field_errors }} +... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> +... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> +... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> +... <input type="submit" /> +... </form>''') +>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'})})) +<form action=""> +<ul class="errorlist"><li>Please make sure your passwords match.</li></ul> +<p><label>Your username: <input type="text" name="username" value="django" /></label></p> +<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> +<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> +<input type="submit" /> +</form> """ if __name__ == "__main__": |
