Django CreateView and validation

I am trying to implement shared views in my Django 1.8 application so that Django can take care of the validation / redirect loop for me.

I 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 approved 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 the admin interface to use validators when adding a Client, but this is not the case)

For a real application, I created a ModelForm for the Customer class:

class CustomerForm(ModelForm):

    class Meta:
            model = Customer
            fields = ['custid', 'customer_shortcode', 'description']

      

and the 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 entering invalid data in the generated form.

As far as I can follow from the docs, I only need to override clean () or clean_xxx () in the ModelForm for additional validation, but not for that, but this is really unclear. I would like to keep the information about what the valid value is in as few places as possible, which is what the validator on the ModelField does.

What's missing here? I suspect I am confused between model validation and form validation ...

+3


source to share


1 answer


TL; DR: When specifying these kind of validators in model field definitions, you must pass in instances, not classes ( validators.CIDValidator()

instead of validators.CIDValidator

).

Longer explanation



Django validators must be callers . Trying to call the class you are currently going through will go through the python instantiation sequence, calling __new__

and __init__

, and it will return an instance of that class, but it will do nothing in terms of validating the field value.

The Django subcategories that you subclass also have a method __call__

that gets triggered when you try to invoke an instance of that class, and it takes care of checking and promoting ValidationError

s

+3


source







All Articles