The last unsolved model-validation design issue is the error message
protocol (my work on fields is waiting on it). Let me present the
approach that looks sane to me.

The old Field.default_error_messages dict and corresponding
logic is no longer required (and removed in my branch) as default
error messages live in core/validators now.

In field construction, the custom error logic is plain:

   CharFied.__init__(self, ..., error_messages={}):
       ...
       self.error_messages = error_messages

And it is used as follows:

class Form(...):
   ...
   def full_clean(self):
       ...
       for name, field in self.fields.items():
           try:
               ...
               # clean() calls to_python() and validate(),
               # raising ValidationErrors
               value = field.clean(value)
               ...
           except ValidationError, e:
               e.custom_messages = field.error_messages
               self._errors[name] = self.error_class(e.messages)

The e.custom_messages = field.error_messages binds custom { code:
message } overrides to the ValidationError.
e.messages is a property that returns the list of error messages.

In reality, ValidationError contains only a single error message. The
list is required for aggregating several errors from the validator
collection associated with a field. However, as of now, the
ValidationError class tries to be both a single value and a
collection, resulting in quite a mess.

This is a classic case of the Composite pattern (http://
en.wikipedia.org/wiki/Composite_pattern ), so I propose that
 * ValidationErrors remain single values
 * core/validators gets an additional ValidationErrorComposite class
that derives from ValidationError and has the same interface

It will be used as follows (example for form field, model field
similar):

class Field(...):
   ...
   def clean(self, value, all_values={}):
       if value is not None:
           value = self.to_python(value)
       self.validate(value, all_values)
       return value

   def validate(self, value, all_values={}, form_instance=None):
       value_is_empty = value in validators.EMPTY_VALUES
       if self.required and value_is_empty:
           raise ValidationError(_("This field is required."),
                   validators.REQUIRED)

       error_collection = ValidationErrorComposite()

       for validator in self.validators:
           if value_is_empty and not getattr(validator, 'always_test',
False):
               continue
           try:
               validator(value, all_values)
           except ValidationError, e:
               error_collection.add(e)

       if error_collection:
           raise error_collection

User code can remain oblivious of the composite, catching
ValidationErrors as before and using them as specified.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to