Hi, see inline text. On Wed, Feb 18, 2009 at 1:28 PM, mrts <m...@mrts.pri.ee> wrote: > > 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.
What if I want to use the same error_messages on multiple instances of a given field? Now I would subclass the FormField and override it's default_messages, with your approach it would require overriding __init__. I am not saying that that is a bad thing, just that it still has a reason. Besides not all validation will be done inside validators, some will remain on the Field classes. > > 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 What if then validators want to raise multiple messages? Of FormFields for that matter? for example: "Must be greated than 1000." "If field Y is supplied, X must be greater than Y." "I don't like your shoes!" Would they then raise ValidationErrorComposite instead? So you just pushed the check to a different layer. I agree that it makes more sense in it's new location, but the distinction still has to be made. And how would ValidationErrorComposite.add(exception) work then? It would have to check the exception type to know whether to append or extend it's message list. I agree that handling of different datat types (string, list or dict) in ValidationError isn't pretty, but it IMHO greatly simplifies it's usage and handling. > > 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): unrelated to custom messages - you cannot pass all_values to field for validation, because at the time field validation is called, not all fields have been cleaned. That's why validator handling is done in (form/model).clean. > 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 -~----------~----~----~----~------~----~------~--~---