Fixed #4752 -- Make default ErrorList customisable in newforms display. Based on a patch from michal@logix.cz and SmileyChris.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@6142 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-09-13 23:09:40 +00:00
parent a7d0ad67dc
commit ce249d4366
3 changed files with 54 additions and 4 deletions

View File

@ -57,13 +57,15 @@ class BaseForm(StrAndUnicode):
# class is different than Form. See the comments by the Form class for more # class is different than Form. See the comments by the Form class for more
# information. Any improvements to the form API should be made to *this* # information. Any improvements to the form API should be made to *this*
# class, not to the Form class. # class, not to the Form class.
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None): def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList):
self.is_bound = data is not None or files is not None self.is_bound = data is not None or files is not None
self.data = data or {} self.data = data or {}
self.files = files or {} self.files = files or {}
self.auto_id = auto_id self.auto_id = auto_id
self.prefix = prefix self.prefix = prefix
self.initial = initial or {} self.initial = initial or {}
self.error_class = error_class
self._errors = None # Stores the errors after clean() has been called. self._errors = None # Stores the errors after clean() has been called.
# The base_fields class attribute is the *class-wide* definition of # The base_fields class attribute is the *class-wide* definition of
@ -117,7 +119,7 @@ class BaseForm(StrAndUnicode):
output, hidden_fields = [], [] output, hidden_fields = [], []
for name, field in self.fields.items(): for name, field in self.fields.items():
bf = BoundField(self, field, name) bf = BoundField(self, field, name)
bf_errors = ErrorList([escape(error) for error in bf.errors]) # Escape and cache in local variable. bf_errors = self.error_class([escape(error) for error in bf.errors]) # Escape and cache in local variable.
if bf.is_hidden: if bf.is_hidden:
if bf_errors: if bf_errors:
top_errors.extend(['(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors]) top_errors.extend(['(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors])
@ -168,7 +170,7 @@ class BaseForm(StrAndUnicode):
field -- i.e., from Form.clean(). Returns an empty ErrorList if there field -- i.e., from Form.clean(). Returns an empty ErrorList if there
are none. are none.
""" """
return self.errors.get(NON_FIELD_ERRORS, ErrorList()) return self.errors.get(NON_FIELD_ERRORS, self.error_class())
def full_clean(self): def full_clean(self):
""" """
@ -241,7 +243,7 @@ class BoundField(StrAndUnicode):
Returns an ErrorList for this field. Returns an empty ErrorList Returns an ErrorList for this field. Returns an empty ErrorList
if there are none. if there are none.
""" """
return self.form.errors.get(self.name, ErrorList()) return self.form.errors.get(self.name, self.form.error_class())
errors = property(_errors) errors = property(_errors)
def as_widget(self, widget=None, attrs=None): def as_widget(self, widget=None, attrs=None):

View File

@ -554,6 +554,29 @@ method you're using::
<p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p> <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p> <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
Customizing the error list format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default, forms use ``django.newforms.util.ErrorList`` to format validation
errors. If you'd like to use an alternate class for displaying errors, you can
pass that in at construction time::
>>> from django.newforms.util import ErrorList
>>> class DivErrorList(ErrorList):
... def __unicode__(self):
... return self.as_divs()
... def as_divs(self):
... if not self: return u''
... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self])
>>> f = ContactForm(data, auto_id=False, error_class=DivErrorList)
>>> f.as_p()
<div class="errorlist"><div class="error">This field is required.</div></div>
<p>Subject: <input type="text" name="subject" maxlength="100" /></p>
<p>Message: <input type="text" name="message" value="Hi there" /></p>
<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div>
<p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
More granular output More granular output
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~

View File

@ -3821,6 +3821,31 @@ u''
True True
>>> f.cleaned_data['username'] >>> f.cleaned_data['username']
u'sirrobin' u'sirrobin'
#######################################
# Test overriding ErrorList in a form #
#######################################
>>> from django.newforms.util import ErrorList
>>> class DivErrorList(ErrorList):
... def __unicode__(self):
... return self.as_divs()
... def as_divs(self):
... if not self: return u''
... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self])
>>> class CommentForm(Form):
... name = CharField(max_length=50, required=False)
... email = EmailField()
... comment = CharField()
>>> data = dict(email='invalid')
>>> f = CommentForm(data, auto_id=False, error_class=DivErrorList)
>>> print f.as_p()
<p>Name: <input type="text" name="name" maxlength="50" /></p>
<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div>
<p>Email: <input type="text" name="email" value="invalid" /></p>
<div class="errorlist"><div class="error">This field is required.</div></div>
<p>Comment: <input type="text" name="comment" /></p>
""" """
__test__ = { __test__ = {