DEV Community

loading...

Validating Django models that are created without forms

foadmoha profile image foadmoha Originally published at foadmoha.com Updated on ・2 min read

Usually instances of models (objects) are created using a ModelForm. You know the drill: The user inputs some values in the form, hits submit and sends a POST request with the data. In the view function/class, we do a model validation using form.is_valid() and then save the object in the database. This gives a basic level of validation for the model fields.

But what if we want to do a more comprehensive validation on the object? And what about a scenario where we want to create objects in some other way than using forms? Let's say through an API call. How do we validate the objects in that case?

That is what validators are for. Validators are callable functions that will check the object fields and raise ValidationError if they contain values that don't meet our desired criteria. In case of ModelForm the validation is done when we call form.is_valid(). Note that if we create an instance of the model ourselves, validators will not be run automatically. So we need to validate the objects first before saving them.

Let's say we have a model called Person. Each person has a first name, a last name and an age. And for some reason, we don't want to save the person in our database if their age is less than 18. We can create a validator that checks for that.

In models.py:

from django.db import models
from django.core.exceptions import ValidationError

def validate_age(value):
    if value < 18:
        raise ValidationError(
            ('Age must be at least 18.'),
            params={'value': value},
        )

class Person(models.Model):
    first_name = models.CharField()
    last_name = models.CharField()
    age = models.IntegerField(validators=[validate_age])
Enter fullscreen mode Exit fullscreen mode

Now just before we save the object, we ask django to validate it by calling the full_clean() method.

In views.py:

from myapp.models import Person
from django.core.exceptions import ValidationError

# let's create an object
person = Person()
person.first_name = "John"
person.last_name  = "Doe"
person.age = 17

try:
    person.full_clean()
    person.save()

except ValidationError:
    # Do something with the error here.
    # Maybe display to user or log it somewhere.
Enter fullscreen mode Exit fullscreen mode

person.full_clean() will run the relevant validators for all fields of the person object. In this case it will run the validate_age function on the person.age field and throws an exception. This prevents this object from being saved. So young John will not be saved into the database! 🙂

signup

Discussion (0)

Forem Open with the Forem app