Reputation: 822
I'm trying to implement generic views in my Django 1.8 app, so that Django can take care of the validation/redirection loop for me.
I've created a model:
class Customer(models.Model):
custid = models.CharField(max_length=4, verbose_name='CID (4 alphanumeric uppercase)', validators=[validators.CIDValidator])
customer_shortcode = models.CharField(max_length=7, verbose_name='Customer Code (7 chars, uppercase, no spaces)', validators=[validators.ShortnameValidator])
description = models.CharField(max_length=30, blank=True)
and defined a validator for each of my two validated fields:
class CIDValidator(RegexValidator):
regex = r'^[A-Z0-9]{4}$'
message = 'CID is a 4-character uppercase alphanumeric value'
class ShortnameValidator(RegexValidator):
regex = r'^[A-Z0-9_]{1,7}$'
message = 'Shortname should be uppercase, no spaces, alphanumeric'
(At this point, I expected that the admin interface would use the validators when I added a Customer, but it doesn't)
For the actual app, I've created a ModelForm for the Customer class:
class CustomerForm(ModelForm):
class Meta:
model = Customer
fields = ['custid', 'customer_shortcode', 'description']
and a View class inherited from CreateView:
class CustomerCreateView(CreateView):
model = Customer
form_class = CustomerForm
def get_success_url(self):
return reverse('customer_list')
And I still don't get validation errors when I enter invalid data in the generated form.
As far as I can follow from the docs, I should only need to override clean() or clean_xxx() on the ModelForm for additional validation, not for this, but it's really unclear. I'd like to keep the knowledge about what constitutes a valid value in as few places as possible - which the validator on the ModelField would do.
What is missing here? I suspect I'm getting confused between model validation and form validation...
Upvotes: 3
Views: 2402
Reputation: 948
TL;DR: when specifying this kind of validators in model field definitions, you should pass instances rather than classes (validators.CIDValidator()
instead of validators.CIDValidator
).
Longer explanation
Django validators need to be callables. Trying to call the class you are passing now will go through python's creation sequence for an instance, calling __new__
and __init__
, and it would return an instance of that class - but it won't do anything in terms of validating the field value.
The Django validators you are subclassing also have a __call__
method, that is run when you try to call an instance of that class, and it takes care of validating and raising ValidationError
s
Upvotes: 3