如何确保 Django 模型中只有一个条目为 True?

nor*_*mic 6 python django django-models

我一直在考虑实施“对于一种组合来说只有一个条目可能为真”。

一个项目通过一个中间表有n个成员(警卫)。

  • 每个 Guard 可能是 n 个项目的成员
  • 仅允许 Guard <-> Project 的一种组合 (unique_together)
  • 会员资格可能是“主要”会员资格 (is_main)
  • 但是:只有一个成员资格可以是主要成员资格。

我是否需要监督某些事情,或者我是否必须自己实施自定义验证?

要完成此操作,请参阅给定的模型:

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']
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 8

您可以使用已过滤的UniqueConstraint\xc2\xa0 [Django-doc] :

\n
from django.db.models import UniqueConstraint, Q\n\nclass ProjectMembership(models.Model):\n    guard = models.ForeignKey(Guard, on_delete=models.CASCADE)\n    project = models.ForeignKey(Project, on_delete=models.CASCADE)\n    is_main = models.BooleanField(_(\'is main project\'), default=False)\n\n    class Meta:\n        constraints = [\n            UniqueConstraint(fields=(\'guard\', \'project\'), name=\'unique_guard\'),\n            UniqueConstraint(fields=(\'guard\',), condition=Q(is_main=True), name=\'one_main_project_per_guard\'),\n        ]
Run Code Online (Sandbox Code Playgroud)\n

因此,这里我们确保,如果我们过滤ProjectMembershipis_main=True则 s 的集合guard是唯一的,因此某个Guard只能在 中出现一次is_main,这意味着a至多Guard有一个是。Projectis_mainTrue

\n
\n
\n

注意:正如\xc2\xa0 [Django-doc]上的文档unique_together所述,该unique_together约束可能会被弃用。该文档建议使用Django约束框架中的UniqueConstraint\xc2\xa0 [Django-doc]

\n
\n