Author: Honza_Kral
Date: 2009-07-19 15:55:58 -0500 (Sun, 19 Jul 2009)
New Revision: 11271

Modified:
   django/branches/soc2009/model-validation/django/db/models/base.py
   
django/branches/soc2009/model-validation/tests/modeltests/validation/__init__.py
   
django/branches/soc2009/model-validation/tests/modeltests/validation/models.py
   django/branches/soc2009/model-validation/tests/modeltests/validation/tests.py
   
django/branches/soc2009/model-validation/tests/modeltests/validation/validators.py
Log:
[soc2009/model-validation] Added capacity for ComplexValidator handling to 
models

Modified: django/branches/soc2009/model-validation/django/db/models/base.py
===================================================================
--- django/branches/soc2009/model-validation/django/db/models/base.py   
2009-07-19 20:55:34 UTC (rev 11270)
+++ django/branches/soc2009/model-validation/django/db/models/base.py   
2009-07-19 20:55:58 UTC (rev 11271)
@@ -10,6 +10,7 @@
 
 import django.db.models.manager     # Imported to register signal handler.
 from django.core.exceptions import ObjectDoesNotExist, 
MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS
+from django.core import validators
 from django.db.models.fields import AutoField, FieldDoesNotExist
 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, 
OneToOneField
 from django.db.models.query import delete_objects, Q
@@ -760,6 +761,20 @@
                 setattr(self, f.attname, f.clean(getattr(self, f.attname), 
self))
             except ValidationError, e:
                 errors[f.name] = e.messages
+
+        # run complex validators after the fields have been cleaned since they
+        # need access to model_instance.
+        for f in self._meta.fields:
+            if f.name in errors:
+                continue
+
+            value = getattr(self, f.attname)
+            for v in f.validators:
+                if isinstance(v, validators.ComplexValidator):
+                    try:
+                        v(value, obj=self)
+                    except ValidationError, e:
+                        errors.setdefault(f.name, []).extend(e.messages)
         try:
             # TODO: run this only if not errors??
             self.validate()

Modified: 
django/branches/soc2009/model-validation/tests/modeltests/validation/__init__.py
===================================================================
--- 
django/branches/soc2009/model-validation/tests/modeltests/validation/__init__.py
    2009-07-19 20:55:34 UTC (rev 11270)
+++ 
django/branches/soc2009/model-validation/tests/modeltests/validation/__init__.py
    2009-07-19 20:55:58 UTC (rev 11271)
@@ -9,5 +9,13 @@
             clean()
         except ValidationError, e:
             self.assertEquals(sorted(failed_fields), 
sorted(e.message_dict.keys()))
+    
+    def assertFieldFailsValidationWithMessage(self, clean, field_name, 
message):
+        self.assertRaises(ValidationError, clean)
+        try:
+            clean()
+        except ValidationError, e:
+            self.assertTrue(field_name in e.message_dict)
+            self.assertEquals(message, e.message_dict[field_name])
 
 

Modified: 
django/branches/soc2009/model-validation/tests/modeltests/validation/models.py
===================================================================
--- 
django/branches/soc2009/model-validation/tests/modeltests/validation/models.py  
    2009-07-19 20:55:34 UTC (rev 11270)
+++ 
django/branches/soc2009/model-validation/tests/modeltests/validation/models.py  
    2009-07-19 20:55:58 UTC (rev 11271)
@@ -1,6 +1,7 @@
 from datetime import datetime
 
 from django.core.exceptions import ValidationError
+from django.core.validators import ComplexValidator
 from django.db import models
 from django.test import TestCase
 
@@ -8,13 +9,21 @@
     if value != 42:
         raise ValidationError('This is not the answer to life, universe and 
everything!')
 
+class ValidateFieldNotEqualsOtherField(ComplexValidator):
+    def __init__(self, other_field):
+        self.other_field = other_field
+
+    def __call__(self, value, all_values={}, obj=None):
+        if value == self.get_value(self.other_field, all_values, obj):
+            raise ValidationError("Must not equal to %r's value" % 
self.other_field)
+
 class ModelToValidate(models.Model):
     name = models.CharField(max_length=100)
     created = models.DateTimeField(default=datetime.now)
     number = models.IntegerField()
     parent = models.ForeignKey('self', blank=True, null=True)
     email = models.EmailField(blank=True)
-    f_with_custom_validator = models.IntegerField(blank=True, null=True, 
validators=[validate_answer_to_universe])
+    f_with_custom_validator = models.IntegerField(blank=True, null=True, 
validators=[validate_answer_to_universe, 
ValidateFieldNotEqualsOtherField('number')])
 
     def validate(self):
         super(ModelToValidate, self).validate()

Modified: 
django/branches/soc2009/model-validation/tests/modeltests/validation/tests.py
===================================================================
--- 
django/branches/soc2009/model-validation/tests/modeltests/validation/tests.py   
    2009-07-19 20:55:34 UTC (rev 11270)
+++ 
django/branches/soc2009/model-validation/tests/modeltests/validation/tests.py   
    2009-07-19 20:55:58 UTC (rev 11271)
@@ -11,7 +11,7 @@
 class BaseModelValidationTests(ValidationTestCase):
 
     def test_missing_required_field_raises_error(self):
-        mtv = ModelToValidate()
+        mtv = ModelToValidate(f_with_custom_validator=42)
         self.assertFailsValidation(mtv.clean, ['name', 'number'])
     
     def test_with_correct_value_model_validates(self):

Modified: 
django/branches/soc2009/model-validation/tests/modeltests/validation/validators.py
===================================================================
--- 
django/branches/soc2009/model-validation/tests/modeltests/validation/validators.py
  2009-07-19 20:55:34 UTC (rev 11270)
+++ 
django/branches/soc2009/model-validation/tests/modeltests/validation/validators.py
  2009-07-19 20:55:58 UTC (rev 11271)
@@ -11,4 +11,26 @@
     def test_custom_validator_raises_error_for_incorrect_value(self):
         mtv = ModelToValidate(number=10, name='Some Name', 
f_with_custom_validator=12)
         self.assertFailsValidation(mtv.clean, ['f_with_custom_validator'])
+        self.assertFieldFailsValidationWithMessage(
+                mtv.clean,
+                'f_with_custom_validator',
+                [u'This is not the answer to life, universe and everything!']
+            )
 
+    def test_custom_complex_validator_raises_error_for_incorrect_value(self):
+        mtv = ModelToValidate(number=42, name='Some Name', 
f_with_custom_validator=42)
+        self.assertFailsValidation(mtv.clean, ['f_with_custom_validator'])
+        self.assertFieldFailsValidationWithMessage(
+                mtv.clean,
+                'f_with_custom_validator',
+                [u"Must not equal to 'number''s value"]
+            )
+
+
+    def test_complex_validator_isnt_run_if_field_doesnt_clean(self):
+        mtv = ModelToValidate(number=32, name='Some Name', 
f_with_custom_validator=32)
+        self.assertFieldFailsValidationWithMessage(
+                mtv.clean,
+                'f_with_custom_validator',
+                [u'This is not the answer to life, universe and everything!']
+            )


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

Reply via email to