Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django CreateView and validation

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...

like image 887
AnotherHowie Avatar asked May 08 '26 04:05

AnotherHowie


1 Answers

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 ValidationErrors

like image 175
Andrei Avram Avatar answered May 09 '26 16:05

Andrei Avram



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!