Django Postgres条件约束

5
我正在尝试为我的模型字段(数据库角度上的列)设置有条件的唯一约束,以便根据另一个布尔字段来进行控制,但是找不到实现的方法。
我正在创建一个基于编号卡片的网页管理工具,用于在顾客仍在店内时帮助/控制其出勤情况。我的主要目标是防止用户在此编号仍处于活动状态(即布尔字段)与其他顾客相关时保存该卡号。
以下是models.py中类似的内容:
    class Cards(models.Model):
         card_number = models.PositiveIntegerField("""{{RESTRICTION NEEDED}}""")
         card_date = models.DateTimeField(auto_now=False, auto_now_add=True)
         custumer = models.ForeignKey(Customer)
         status = models.BooleanField(default=False)

也许这种方法可以直接在Postgres上工作,但我还没有尝试过。
CREATE UNIQUE INDEX card_number_ind ON Cards (card_number) WHERE (status is False);

有没有可能直接使用Django来完成?我的意思是,针对Django上的布尔字段(状态),设置一个有条件的唯一性约束?
谢谢您的提问。 注:这是我在stackoverflow上的第一个问题,请随意批评我的风格。

1
你不应该在models.py中这样做,尽可能地分离逻辑和数据。你使用表单或其他方式保存卡号吗? - Shang Wang
1
你可以修改save()方法或设置模型验证(如果你正在使用表单)来检查状态。 - Yaaaaaaaaaaay
1
@Shang Wang,这并不是逻辑问题-数据库模式应正确地建模数据。就像您希望在常规数据库中确保某些列是唯一的(例如用户的电子邮件)一样,在Felicio的情况下,当状态为False时,card_number应该是唯一的。通过约束条件,它保证了数据库永远不会有相同的card_number,其中状态为False。 - Derek Kwok
@ShangWang 是的,是表单。我会尝试Derek的解决方案并在之后报告。 - Felício
1
是的,Derek的解决方案符合我所需的限制。谢谢! - Felício
2个回答

5

Django不支持在models.py中定义条件约束,但是您可以创建一个迁移来添加这样的约束。

首先创建一个空的迁移。

./manage.py makemigrations appname --empty

这将创建一个空的迁移文件。接下来,您需要将自定义约束添加到迁移中。

class Migration(migrations.Migration):

    ... 

    operations = [
        migrations.RunSQL('create unique index card_number_ind on cards (card_number) where (status is false)'),
    ]

3
Django 2.2开始,现在有一个可用的UniqueConstraint声明,其中包含一个condition选项。 条件

UniqueConstraint.condition

一个指定约束条件的Q对象。
例如:
UniqueConstraint(fields=['user'], condition=Q(status='DRAFT'), name='unique_draft_user')

确保每个用户只有一个草稿。

它适用于非唯一情况吗?比如说,当另一个字段中有特定值时,我想要使一个字段变为必填项。 - Sandeep Balagopal
1
@SandeepBalagopal 是的,您也可以创建复杂的约束。您可能还会对django-pgtriggers感兴趣。 - rrauenza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接