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:
parent
55e23d5efa
commit
b59bfbd128
@ -118,6 +118,32 @@ class Field(object):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
Returns the database column data type for this field, taking into
|
||||
@ -355,6 +381,9 @@ class AutoField(Field):
|
||||
raise exceptions.ValidationError(
|
||||
_("This value must be an integer."))
|
||||
|
||||
def validate(self, value, model_instance):
|
||||
pass
|
||||
|
||||
def get_db_prep_value(self, value):
|
||||
if value is None:
|
||||
return None
|
||||
@ -417,14 +446,8 @@ class CharField(Field):
|
||||
return "CharField"
|
||||
|
||||
def to_python(self, value):
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, basestring) or value is None:
|
||||
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)
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
|
@ -678,6 +678,11 @@ class ForeignKey(RelatedField, Field):
|
||||
|
||||
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):
|
||||
return '%s_id' % self.name
|
||||
|
||||
@ -766,6 +771,14 @@ class OneToOneField(ForeignKey):
|
||||
return None
|
||||
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):
|
||||
def __init__(self, to, **kwargs):
|
||||
try:
|
||||
|
@ -132,3 +132,45 @@ class SlugFieldTests(django.test.TestCase):
|
||||
bs = BigS.objects.get(pk=bs.pk)
|
||||
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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user