How to access self in Model validator django

Viewed 271

I have a Model in django with a field:

child = models.ForeignKey(Child, on_delete=models.SET_NULL)

def validate_child(child):
        if child.parent = self:
               RAISE ERR HERE

As you can see, I want to access self in the validate_child method. How can I do this? Thanks.

2 Answers

Unfortunately, it would seem that the only solution is the one proposed by Willem:

Override clean method, since we actually want to make cross-fields validations.

I tried to use a class method as a custom validator, positioning it before the field, like:

enter image description here

But by default, the validator passes one and only one parameter to the function it uses (the method validate_age_range in this case), so with this exact code an exception is raised because the parameter is assigned to 'self' and therefore, 'value' is not filled, but expected.

If you remove 'value', then self (or whatever name you use for the first method parameter) is filled with the parameter passed by the validator, but you loose access to the class, which is the whole point.

Therefore: Dead end.

BTW: the @classmethod annotation is because I also tried using a class method to see if the first parameter is filled, but it also raised an exception:

enter image description here

If you are using class-based views then you can pass the self and the parent object to the custom validator function

Here is the article from the official docs on validators

A validator is a callable that takes a value and raises a ValidationError if it doesn’t meet some criteria. Validators can be useful for re-using validation logic between different types of fields.

For example, here’s a validator that only allows even numbers:

from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

def validate_even(value):
    if value % 2 != 0:
        raise ValidationError(
            _('%(value)s is not an even number'),
            params={'value': value},
        )

You can add this to a model field via the field’s validators argument:

from django.db import models

class MyModel(models.Model):
    even_field = models.IntegerField(validators=[validate_even])

Because values are converted to Python before validators are run, you can even use the same validator with forms:

from django import forms

class MyForm(forms.Form):
    even_field = forms.IntegerField(validators=[validate_even])
Related