Validation of custom Django fields
There is a Django field type for storin开发者_运维技巧g values of MyType
.
from django.core.exceptions import ValidationError
from django.db import models
class MyTypeField(models.Field):
__metaclass__ = models.SubfieldBase
def db_type(self, connection):
return "text"
def to_python(self, value):
if isinstance(value, basestring):
try:
value = MyType.deserialize(value)
except ParseError, e:
raise ValidationError("Invalid format: "+str(e))
assert isinstance(value, MyType)
return value
def get_prep_value(self, value):
if not isinstance(value, MyType):
raise ValidationError("Not MyType")
return value.serialize()
I am trying to use fields of this type on an admin page of a model. Everything works nice if a user enters a valid value in the field. But if the entered value is invalid, the ValidationError
is not caught (you get error 500, or a stack trace if debug is enabled)
Instead I want to see the form with a message "Invalid format" near the field (just like if you enter an invalid date or number). How to modify the field class to get validation errors in a correct place.
Quoting from http://docs.djangoproject.com/en/1.2/howto/custom-model-fields/#modelforms-and-custom-fields
If you use SubfieldBase, to_python() will be called every time an instance of the field is assigned a value. This means that whenever a value may be assigned to the field, you need to ensure that it will be of the correct datatype, or that you handle any exceptions.
So a ValidationError will never be caught at this point. to_python
is also called when populating a new instance of your model from the database, which is outside the form validation context.
Therefore, you must ensure that the form field used to represent your custom field performs whatever input validation and data cleaning is necessary to convert user-provided form input into a to_python()-compatible model field value. This may require writing a custom form field, and/or implementing the formfield() method on your field to return a form field class whose to_python() returns the correct datatype.
So you have to move your validation into a formfield.
You need to create a clean(self, value, model_instance)
method in your field class and do the validation/raise the error there.
精彩评论