Search code examples
djangounique

Unique value in django model field


I have the following code:

from django.db import models
from django.contrib.auth import get_user_model

User = get_user_model()


class Employee(models.Model):
    employee = models.OneToOneField(User, on_delete=models.CASCADE)
    boss = models.ForeignKey(
        "self",
        on_delete=models.CASCADE,
        null=True,
        blank=True),
    )
    executive_head = models.BooleanField(
        default=False,
        help_text=_("e.g. Chief Executive Officer or Managing Director."),
    )
    job_title = models.CharField(max_length=100)

    class Meta:
        ordering = ["id"]
        constraints = [
            UniqueConstraint(
                fields=["executive_head"],
                name="only_one_executive_head",
                condition=Q(executive_head=True),
            )
        ]

    def __str__(self):
        return f"{ self.employee }"

    def save(self, *args, **kwargs):

        if self.employee == self.boss:
            self.executive_head = True
        else:
            self.executive_head = False

    def clean(self):
        if Employee.objects.filter(executive_head=True) and 
           self.employee == self.boss:
            raise ValidationError(
                {"executive_head": _("There can only be one executive          
                  head.")
                }
            )

What I would like to see is that only one value should be true in the executive_head field. It should not be possible to have more than one executive head.

Using unique_together in the class Meta does not work (in hindsight it should not) because the false values would then not be unique.

Any ideas?


Solution

  • Solved using my last suggestion and doing away with the class meta unique_constraint. Amended models.py. See the code. I beg your pardon that I didn't share the "boss" field. Only executive head can be own boss hence clean method works. As a result of the save method, the executive head is automatically updated and the clean method ensures no multiple executive heads.