1
0
mirror of https://github.com/django/django.git synced 2025-07-07 19:29:12 +00:00

[soc2009/model-validation] Implemented some basic validation on model Fields including basic tests.

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@10868 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Honza Král 2009-06-01 15:38:34 +00:00
parent 55e23d5efa
commit b59bfbd128
3 changed files with 85 additions and 7 deletions

View File

@ -117,6 +117,32 @@ class Field(object):
Returns the converted value. Subclasses should override this. Returns the converted value. Subclasses should override this.
""" """
return value return value
def validate(self, value, model_instance):
"""
Validates value and throws ValidationError. Subclasses should override
this to provide validation logic.
"""
if not self.editable:
# skip validation for non-editable fields
return
if self._choices and value:
if not value in dict(self.choices):
raise exceptions.ValidationError(_('Value %r is not a valid choice.') % value)
if value is None and not self.null:
raise exceptions.ValidationError(
ugettext_lazy("This field cannot be null."))
def clean(self, value, model_instance):
"""
Convert the value's type and wun validation. Validation errors from to_python
and validate are propagated. The correct value is returned if no error is
raised.
"""
value = self.to_python(value)
self.validate(value, model_instance)
return value
def db_type(self): def db_type(self):
""" """
@ -354,6 +380,9 @@ class AutoField(Field):
except (TypeError, ValueError): except (TypeError, ValueError):
raise exceptions.ValidationError( raise exceptions.ValidationError(
_("This value must be an integer.")) _("This value must be an integer."))
def validate(self, value, model_instance):
pass
def get_db_prep_value(self, value): def get_db_prep_value(self, value):
if value is None: if value is None:
@ -417,14 +446,8 @@ class CharField(Field):
return "CharField" return "CharField"
def to_python(self, value): def to_python(self, value):
if isinstance(value, basestring): if isinstance(value, basestring) or value is None:
return value return value
if value is None:
if self.null:
return value
else:
raise exceptions.ValidationError(
ugettext_lazy("This field cannot be null."))
return smart_unicode(value) return smart_unicode(value)
def formfield(self, **kwargs): def formfield(self, **kwargs):

View File

@ -678,6 +678,11 @@ class ForeignKey(RelatedField, Field):
self.db_index = True self.db_index = True
def validate(self, value, model_instance):
if self.rel.parent_link:
return
super(ForeignKey, self).validate(value, model_instance)
def get_attname(self): def get_attname(self):
return '%s_id' % self.name return '%s_id' % self.name
@ -766,6 +771,14 @@ class OneToOneField(ForeignKey):
return None return None
return super(OneToOneField, self).formfield(**kwargs) return super(OneToOneField, self).formfield(**kwargs)
def save_form_data(self, instance, data):
# FIXME: is this a hack, or what? it works, but I don't really know why
if isinstance(data, self.rel.to):
setattr(instance, self.name, data)
else:
setattr(instance, self.attname, data)
class ManyToManyField(RelatedField, Field): class ManyToManyField(RelatedField, Field):
def __init__(self, to, **kwargs): def __init__(self, to, **kwargs):
try: try:

View File

@ -132,3 +132,45 @@ class SlugFieldTests(django.test.TestCase):
bs = BigS.objects.get(pk=bs.pk) bs = BigS.objects.get(pk=bs.pk)
self.assertEqual(bs.s, 'slug'*50) self.assertEqual(bs.s, 'slug'*50)
class ValidationTest(django.test.TestCase):
def test_charfield_cleans_empty_string(self):
f = models.CharField()
self.assertEqual('', f.clean('', None))
def test_integerfield_cleans_valid_string(self):
f = models.IntegerField()
self.assertEqual(2, f.clean('2', None))
def test_integerfield_raises_error_on_invalid_intput(self):
f = models.IntegerField()
self.assertRaises(ValidationError, f.clean, "a", None)
def test_charfield_with_choices_cleans_valid_choice(self):
f = models.CharField(choices=[('a','A'), ('b','B')])
self.assertEqual('a', f.clean('a', None))
def test_charfield_with_choices_raises_error_on_invalid_choice(self):
f = models.CharField(choices=[('a','A'), ('b','B')])
self.assertRaises(ValidationError, f.clean, "not a", None)
def test_nullable_integerfield_cleans_none(self):
f = models.IntegerField(null=True)
self.assertEqual(None, f.clean(None, None))
def test_integerfield_raises_error_on_empty_input(self):
f = models.IntegerField(null=False)
self.assertRaises(ValidationError, f.clean, None, None)
self.assertRaises(ValidationError, f.clean, '', None)
def test_charfield_raises_error_on_empty_input(self):
f = models.CharField(null=False)
self.assertRaises(ValidationError, f.clean, None, None)
def test_datefield_cleans_date(self):
f = models.DateField()
self.assertEqual(datetime.date(2008, 10, 10), f.clean('2008-10-10', None))
def test_boolean_field_doesnt_accept_empty_input(self):
f = models.BooleanField()
self.assertRaises(ValidationError, f.clean, None, None)