通过字段值约束Django模型

时间:2019-06-18 23:47:43

标签: django

考虑以下Django模型:

class Account(models.Model):

    ACCOUNT_CHOICES = [
        ('m', 'Main',),
        ('s','Secondary'),
        ('o', 'Other')
    ]
    user = models.ForeignKey(User)
    level = models.CharField(max_length=1, choices=ACCOUNT_CHOICES)

如何在每个用户最多执行一个“主要”帐户的数据库约束,同时仍允许用户使用任何数量的“次要”或“其他”帐户?从某种意义上说,我希望unique_together代表userlevel,但仅当level的值为m时。

我知道我可以手动检查保存,但是我希望数据库能够自动检查并在适当的时候引发IntegrityError

1 个答案:

答案 0 :(得分:2)

我认为您无法使用当前模型进行此操作,但是例如,如果这些是level字段的唯一两个选择,请考虑将其更改为可为空的BooleanField,例如

is_main = models.BooleanField(null=True) 

,然后将其设置为None(用于辅助帐户)。然后unique_together将起作用,因为就SQL而言,每个空值都是唯一的(请参见this answer)。

由于后面将要说明的level字段还有更多选择,因此您可以添加第三个字段,并可能覆盖.save()方法,以使其自动设置为None,如果{ {1}}并非level,这是为了提供更多便利。

编辑::如果您不担心可移植性,@Trent建议PostgreSQL支持部分唯一索引,例如:

"m"

这里是SQL Fiddle

编辑2:实际上,看来终于可以从Django 2.2开始在Django ORM中创建部分索引了。有关详细信息,请参见this question