Sandy
Sandy

Reputation: 2692

Validation not ocurring for custom field type in Django

I'm attempting to make a custom type in Django:

from django.db.models import DecimalField
from django.core import validators
from django.utils.functional import cached_property


class MinOneHundredDecimalField(DecimalField):
    @cached_property
    def validators(self):
        return super().validators + [
            validators.MinValueValidator(100, "Minimum value is 100"),
        ]

And I use this in my model:

class MyModel(BaseModel):
    amount = MinOneHundredDecimalField(
        decimal_places=2,
        max_digits=6,
    )

However when testing, I'm able to set amount to a value less than 100:

def test_min_val(self):
    my_model = MyModel(amount=50)
    my_model.save()
    self.assertNotEqual(my_model.amount, 50, "Message here")

I also tried adding the validator directly in the model, but I get the same result:

amount = MinOneHundredDecimalField(
    decimal_places=2,
    max_digits=6,
    validators=[MinValueValidator(100.0, "Minimum value is 0")]
)

Any ideas why this validator isn't working? Ty!

Upvotes: 1

Views: 80

Answers (2)

JPG
JPG

Reputation: 88499

You need to call the full_clean()--(Django doc) method too... So, you have to change the test cases to something like,

from django.core import exceptions

class FooTest(TestCase):
    def test_min_val(self):
        my_model = MyModel(amount=50)

        with self.assertRaises(exceptions.ValidationError) as context:
            my_model.full_clean()

        self.assertIn('Minimum value is 100', context.exception.message_dict['amount'])

Upvotes: 3

Tony
Tony

Reputation: 10327

You should check the documentation on validators, it states

Note that validators will not be run automatically when you save a model

In the section on validating objects it says there are three steps involved in validating a model and they are performed when you call a model’s full_clean() method.

At the moment you are only calling save() which will not trigger the field validation.

You can override the save() method in your model to call full_clean() but be careful doing this if you later use your model linked to a model form, when validation will be performed automatically.

Upvotes: 1

Related Questions