[Apologies if this appears twice. I think Google ate my homework the
first time.]

On Mon, 2007-05-21 at 14:00 -0500, Tim Chase wrote:
> > What is the "general way" to add your own validation to forms under
> > the newforms framework?
> > 
> > Subclassing and adding in your clean_* methods? Using decorators or
> > the such around existing validation? Adding your own custom Field
> > objects and setting their "clean" methods?
> 
> My understanding (easily wrong, and appreciating correction if 
> so) is that they are divergent concepts, each of which serves its 
> own purpose.
[...]

> Perhaps 
> one of the framework gurus could shed light on "the way it should 
> be done"...

Tim's explanation is mostly on the money. Since I have a "framework
guru" T-shirt around here somewhere (actually, I don't -- I want to get
a Django T-shirt one day), here's my understanding.

There are three types of cleaning methods that are run during form
processing. These are all executed when you access Form.errors or call
call Form.full_clean() explicitly (or Form.is_valid(), which accesses
Form.errors).

Any cleaning method can raise ValidationError if there is a problem with
the data it is processing, passing the relevant error message to the
ValidationError's constructor. If no ValidationError is raised, the
method should return a Python object for the cleaned (normalised) data.

The three types of methods are:

        (1) The clean() method on a Field subclass. This is responsible
        for cleaning the data in a way that is generic for that type of
        field. For example, a FloatField will turn the data into a
        Python float or raise a ValidationError.
        
        (2) The clean_fieldname() method -- where "fieldname" is
        replaced with the name of the form field attribute. This method
        does any cleaning that is specific to that particular attribute,
        unrelated to the type of field that it is. In Matt's original
        problem, clean_username() would be the right place to do any
        uniqueness validation. You don't need a specific Username field
        -- it's just a CharField, really -- but you want a
        formfield-specific piece of validation and, possibly, cleaning.
        
        (3) The Form subclass's clean() method. This method can perform
        any validation that requires access to multiple fields from the
        form at once. This is where you might put in things to check
        that if fieldA is supplied, fieldB must contain a valid email
        address and the like. The data that this method returns is the
        final cleaned_data attribute for the form, so don't forget to
        return the full list of cleaned data if you override this method
        (by default, Form.clean() just returns self.cleaned_data).
        
        Note that any errors raised by your Form.clean() override will
        not be associated with any field in particular. They go into a
        special "field" called "__all__", which you can access via
        Form.non_field_errors() if you need to. You don't need to care
        about __all__ at all (ha, ha!).

These methods are run in the order given above, one field at a time.
That is, for each field in the form (in the order they are declared in
the form definition), the Field.clean() method (or it's override) is
run, then clean_<fieldname>(). Finally, once those two methods are run
for every field, the Form.clean() method, or it's override, is executed.

Again, any of these methods can raise a ValidationError. For any field,
if step (1) raises a ValidationError, step (2) is not run, however,
steps (1) and (2) are run for all remaining fields. Regardless of the
results of steps (1) and (2), step (3) is always run. If step (3) raises
a ValidationError, self.cleaned_data will be an empty dictionary.

The previous paragraph means that if you are overriding Form.clean(),
you should iterate through self.cleaned_data.items(), rather than
through the list of fields in the forms: not every field may end up
contributing to cleaned_data, because they may have raised
ValidationErrors themselves, so don't assume you have the data you need
by accessing the form fields directly -- always talk to
self.cleaned_data.

Hopefully that clears up some of the mystery around the various form
validation phases. If somebody wants to write that up as a patch to the
newforms documentation, go crazy.

Regards,
Malcolm



--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to