I'm stuck on thinking about implementing a "only one entry might be True for one combination".
A Project has n members (Guards) through an intermediate table.
- every Guard may be member of n Projects
- only one combination of Guard <-> Project is allowed (unique_together)
- a MemberShip might be the 'Main' one (is_main)
- BUT: Only one of the memberships may be Main.
Do I oversee something or do I have to implement a custom validation on my own?
To complete this, see the given Model:
class Project(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE)
shortname = models.CharField(_('shortname'), max_length=50)
description = models.TextField(_('description'), blank=True)
members = models.ManyToManyField(Guard, through='ProjectMembership')
class Meta:
unique_together = ['client', 'shortname']
class ProjectMembership(models.Model):
guard = models.ForeignKey(Guard, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
is_main = models.BooleanField(_('is main project'), default=False)
class Meta:
unique_together = ['guard', 'project']
CodePudding user response:
You can work with a UniqueConstraint
[Django-doc] that is filtered:
from django.db.models import UniqueConstraint, Q
class ProjectMembership(models.Model):
guard = models.ForeignKey(Guard, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
is_main = models.BooleanField(_('is main project'), default=False)
class Meta:
constraints = [
UniqueConstraint(fields=('guard', 'project'), name='unique_guard'),
UniqueConstraint(fields=('guard',), condition=Q(is_main=True), name='one_main_project_per_guard'),
]
Here we thus ensure that if we filter ProjectMembership
for is_main=True
, that the set of guard
s is unique, hence a certain Guard
can only occur once for is_main
, and this thus means that a Guard
has at most one Project
for which is_main
is True
.
Note: As the documentation on
unique_together
[Django-doc] says, theunique_together
constraint will likely become deprecated. The documentation advises to use theUniqueConstraint
[Django-doc] from Django's constraint framework.