'Django model validator not working on create

I have model with a field validator

from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator

 class MyModel(model.Model):
     name = models.CharField()
     size = models.IntegerField(validators=[MinValueValidator(1),MaxValueValidator(10)])

The validator is working well in the django admin panel ,while I try to enter the value more than 10, it's showing me the error message 'Ensure this value is less than or equal to 10' and does not allow to save.

But, when I try in the django shell, the validator is not working, it allows to save the record, I don't know why is the validator not throwing error message here.

>>>form app.models import MyModel
>>>MyModel.objects.create(name="Some Name", size=15)
<MyModel: Some Name>

Can you please suggest me if anything I missed or any mistake i did here. Kindly help me to solve this problem, it will be very greatfull for me, Thanks in advance.



Solution 1:[1]

Django validation is mostly application level validation and not validation at DB level. Also Model validation is not run automatically on save/create of the model. If you want to validate your values at certain time in your code then you need to do it manually.

For example:

from django.core.exceptions import ValidationError
form app.models import MyModel

instance = MyModel(name="Some Name", size=15)
try:
    instance.full_clean()
except ValidationError:
    # Do something when validation is not passing
else:
    # Validation is ok we will save the instance
    instance.save()

More info you can see at django's documentation https://docs.djangoproject.com/en/1.10/ref/models/instances/#validating-objects

In administration it works automatically because all model forms (ModelForm) will run model validation process alongside form validation.

If you need to validate data because it is coming from untrusted source (user input) you need to use ModelForms and save the model only when the form is valid.

Solution 2:[2]

The validator only works when you are using models in a ModelForm.

https://docs.djangoproject.com/en/dev/ref/validators/#how-validators-are-run

You can perform model validation by overidding clean() and full_clean() methods

Solution 3:[3]

Validators work only with the Forms and model forms. Can't be used with the model definition because it runs at the app side not the DB side.

Solution 4:[4]

You can add this to your model and call it in save().

    def save(self, *args, **kwargs):
        self.run_validators()
        super().save(*args, **kwargs)

    def run_validators(self) -> None:
        for field_name, field_value in model_to_dict(self).items():
            model_field = getattr(UserSearchHistory, field_name)
            field = getattr(model_field, 'field', object())
            validators = getattr(field, 'validators', list())
            for validator_func in validators:
                if field_value is not None:
                    validator_func(field_value)

Solution 5:[5]

From django documentation:

Note that validators will not be run automatically when you save a model, but if you are using a ModelForm, it will run your validators on any fields that are included in your form.

https://docs.djangoproject.com/en/3.1/ref/validators/#how-validators-are-run

Solution 6:[6]

I ran into the same issue. So the validators only work when you are using Forms and Model Form to fill it.

However, by creating in shell, you probably wanted to test the validators before going live. So here is the additional piece of code to help in validating the validators.

>>>form app.models import MyModel
>>>MyModel.size.field.run_validators(value=<undesirable value>)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 sunny
Solution 3 Ibrahim Tayseer
Solution 4
Solution 5 powlo
Solution 6 Abhishek Sahu