Ticket #16986: model-clean-errordict-4.diff
File model-clean-errordict-4.diff, 7.0 KB (added by , 13 years ago) |
---|
-
docs/releases/1.4.txt
477 477 This should make it easier to read when debugging interaction with 478 478 client-side Javascript code. 479 479 480 * :meth:`Model.clean()` can raise :exc:`~django.core.exceptions.ValidationError` with 481 a dictionary, permitting validation errors on individual fields. 482 480 483 .. _backwards-incompatible-changes-1.4: 481 484 482 485 Backwards incompatible changes in 1.4 -
docs/ref/models/instances.txt
115 115 except ValidationError, e: 116 116 non_field_errors = e.message_dict[NON_FIELD_ERRORS] 117 117 118 .. versionadded:: 1.4 119 :meth:`Model.clean()` recognizes :exc:`~django.core.exceptions.ValidationError` with a 120 dictionary. 121 122 Alternatively, it is possible to specify errors for individual fields by providing 123 a dictionary to the :exc:`~django.core.exceptions.ValidationError` constructor that maps field names to messages:: 124 125 def clean(self): 126 from collections import defaultdict 127 from django.core.exceptions import ValidationError 128 129 message_dict = defaultdict(list) 130 if self.min and self.max and (not self.min <= self.max): 131 message_dict['min'].append(u'Min value must be less that or equal to the max value.') 132 message_dict['max'].append(u'Max value must be greater than or equal to the min value.') 133 if len(message_dict): 134 raise ValidationError(message_dict) 135 118 136 Finally, ``full_clean()`` will check any unique constraints on your model. 119 137 120 138 .. method:: Model.validate_unique(exclude=None) -
django/forms/models.py
331 331 try: 332 332 self.instance.clean() 333 333 except ValidationError, e: 334 self._update_errors({NON_FIELD_ERRORS: e.messages}) 334 if e.has_message_dict: 335 self._update_errors(e.message_dict) 336 else: 337 self._update_errors({NON_FIELD_ERRORS: e.messages}) 335 338 336 339 # Validate uniqueness if needed. 337 340 if self._validate_unique: -
django/core/exceptions.py
59 59 self.params = params 60 60 message = force_unicode(message) 61 61 self.messages = [message] 62 62 63 @property 64 def has_message_dict(self): 65 return hasattr(self, 'message_dict') 66 63 67 def __str__(self): 64 68 # This is needed because, without a __str__(), printing an exception 65 69 # instance would result in this: 66 70 # AttributeError: ValidationError instance has no attribute 'args' 67 71 # See http://www.python.org/doc/current/tut/node10.html#handling 68 if hasattr(self, 'message_dict'):72 if self.has_message_dict: 69 73 return repr(self.message_dict) 70 74 return repr(self.messages) 71 75 72 76 def __repr__(self): 73 if hasattr(self, 'message_dict'):77 if self.has_message_dict: 74 78 return 'ValidationError(%s)' % repr(self.message_dict) 75 79 return 'ValidationError(%s)' % repr(self.messages) 76 80 77 81 def update_error_dict(self, error_dict): 78 if hasattr(self, 'message_dict'):82 if self.has_message_dict: 79 83 if error_dict: 80 84 for k, v in self.message_dict.items(): 81 85 error_dict.setdefault(k, []).extend(v) -
tests/modeltests/validation/tests.py
11 11 12 12 from . import ValidationTestCase 13 13 from .models import (Author, Article, ModelToValidate, 14 GenericIPAddressTestModel, GenericIPAddrUnpackUniqueTest )14 GenericIPAddressTestModel, GenericIPAddrUnpackUniqueTest, Range) 15 15 16 16 # Import other tests for this package. 17 17 from .test_custom_messages import CustomMessagesTest … … 196 196 giptm.save() 197 197 giptm = GenericIPAddrUnpackUniqueTest(generic_v4unpack_ip="18.52.18.52") 198 198 self.assertFailsValidation(giptm.full_clean, ['generic_v4unpack_ip',]) 199 200 class RangeForm(forms.ModelForm): 201 class Meta: 202 model = Range 203 204 class ModelCleanPerFieldValidationTests(ValidationTestCase): 205 206 def test_no_errors(self): 207 range = Range(min=0, max=1) 208 range.full_clean() 209 210 form = RangeForm(instance=range) 211 form.full_clean() 212 self.assertEqual({}, form.errors) 213 214 def test_two_errors(self): 215 range = Range(min=999, max=1) 216 self.assertFieldFailsValidationWithMessage(range.full_clean, 'min', [u'Min value must be less that or equal to the max value.']) 217 self.assertFieldFailsValidationWithMessage(range.full_clean, 'max', [u'Max value must be greater than or equal to the min value.']) 218 219 # In particular, the key should not be '__all__' 220 expected_error_dict = { 221 'min': [u'Min value must be less that or equal to the max value.'], 222 'max': [u'Max value must be greater than or equal to the min value.'], 223 } 224 form = RangeForm(data={'min': 999, 'max': 1}) 225 form.full_clean() 226 self.assertEqual(expected_error_dict, form.errors) -
tests/modeltests/validation/models.py
1 from collections import defaultdict 1 2 from datetime import datetime 2 3 3 4 from django.core.exceptions import ValidationError … … 92 93 class GenericIPAddrUnpackUniqueTest(models.Model): 93 94 generic_v4unpack_ip = models.GenericIPAddressField(blank=True, unique=True, unpack_ipv4=True) 94 95 96 class Range(models.Model): 97 min = models.IntegerField() 98 max = models.IntegerField() 99 100 def clean(self): 101 message_dict = defaultdict(list) 102 if self.min and self.max and (not self.min <= self.max): 103 message_dict['min'].append(u'Min value must be less that or equal to the max value.') 104 message_dict['max'].append(u'Max value must be greater than or equal to the min value.') 105 if len(message_dict): 106 raise ValidationError(message_dict) 95 107 96 108 # A model can't have multiple AutoFields 97 109 # Refs #12467. … … 102 114 auto2 = models.AutoField(primary_key=True) 103 115 except AssertionError, assertion_error: 104 116 pass # Fail silently 105 assert str(assertion_error) == u"A model can't have more than one AutoField." 106 No newline at end of file 117 assert str(assertion_error) == u"A model can't have more than one AutoField."