Django 1.8: How can I make sure that out of two fields in a model, at least one or only one must match?

For context, here's the menu system.

class Menu(models.Model):
    ...


class Link(models.Model):
    ...


class MenuItem(models.Model):
    menu = models.ForeignKey(Menu)
    submenu = models.ForeignKey(Menu, related_name='submenu', blank=True, null=True)
    link = models.ForeignKey(Link, blank=True, null=True)
    position = models.IntegerField()

      

I have two results that I want to achieve:

  • At least one submenu and link must not be Null (submenus can have a link)
  • Only one submenu and links must be null (submenus cannot have a link)

Any extended validation is new to me, so a sample code would be very helpful.

In this example, data will only be added via Django Admin

+7


source to share


1 answer


Model validation documentation is poor. There are many (closed) questions regarding this, but it is still unclear.

This solution works without changing any forms:

from django.core.exceptions import ValidationError

class MenuItem(models.Model):
    ...

    def clean(self):
        super(MenuItem, self).clean()
        if self.submenu is None and self.link is None:
            raise ValidationError('Validation error text')

      



clean()

has some default validation functions, so you need to call pure model ownership first.

The above ensures that at least one of the two fields is used and throws an exception if not. I've only tested this in the admin interface.

I don't know if this is the correct way to do it, and would like to know more if someone has a better understanding of model validation in Django. Coming from other languages ​​and frameworks, this seems like a natural way to write custom validation.

+9


source







All Articles