3

In Django I have a parent abstract class with a few common fields, and some subclasses that add more fields. In some of these subclasses I would like to add custom validators that validate fields on the parent class.

class Template(models.Model):
  text = models.CharField(max_length=200)

class GlobalTemplate(Template):
  function = models.ManyToManyField(Function, null=True, blank=True)

I can easily add them on the field in the parent class like this:

class Template(models.Model):
  text = models.CharField(max_length=200, validators=[validate_custom])

But in this case I want to add the validator to my child class GlobalTemplate, but have it attached to the text field.

Is this possible in Django?

Thanks!

brandon
  • 427
  • 3
  • 12
  • Let me see if I understood: you want to put a custom validator on the field `text`, but only in the `GlobalTemplate` subclass and without redefine `text`. Right? – borges May 27 '12 at 20:06

2 Answers2

3

Field validators are stored in field.validators, it's a list, so you basically need to append your validators there.

To access the field instance, you'll have to play a little bit with the _meta attribute of your object (note that you're not supposed to play with this attribute, so when you update django, you'll have to check that it has not changed). Here's how you could do it:

def get_fields_dict(self):
    return dict((field.name, field) for field in self._meta.fields)

def __init__(self, *args, **kwargs):
    super(GlobalTeplate, self).__init__(*args, **kwargs)
    text_field = self.get_fields_dict()['text']
    text_field.validators.append(validate_custom)
Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
  • Where would I add that though? I can't add text.validators = [calidate_custom] in models.py for my subclass, so where is the right place to add to the list of validators for the subclass? – brandon Jun 02 '12 at 01:17
  • Your model's `__init__` method would be totally fine. Don't forget the `super` call though. – Thomas Orozco Jun 02 '12 at 14:15
  • Hrm... maybe I'm totally missing something fundamental, but trying to add `self.text.validators = [validate_custom]` to the init method gives me a "'unicode' object has no attribute 'validators'" error – brandon Jun 03 '12 at 01:41
  • This is wrong. fields (and their validators) are class variables, not instance variables. now you add new validators to the class each time an instance is created. also, it's shared with the base class and with all other children. See: https://stackoverflow.com/questions/12062258 – Noam Nol Apr 18 '23 at 08:40
0

You can add a clean_fields() method to the child model with extra validators.

See: https://stackoverflow.com/a/76033963/10727283

Noam Nol
  • 570
  • 4
  • 11