Django 1.7的documentation提及RunSQL
类可用于在表上创建部分索引。我有一张表格,我想要title
,blog
& category
是独一无二的。但是,如果没有提供类别,则标题和组合的组合。博客应该仍然是独特的。
class Post(models.Model):
title = models.CharField(max_length=200)
blog = models.ForeignKey(Blog)
category = models.ForeignKey(Category, null=True, blank=True)
我可以使用部分索引实现此约束(如下面显示的SQL)。如果我使用Django 1.7迁移,我在哪里添加此代码?
CREATE UNIQUE INDEX idx1
ON Post (title, blog_id, category_id)
WHERE category_id IS NOT NULL;
CREATE UNIQUE INDEX idx2
ON Post (title, blog_id)
WHERE category_id IS NULL;
答案 0 :(得分:20)
Django 2.2及更高版本
从版本2.2开始,Django支持declarative partial unique indexes支持它们的数据库(PostgreSQL和SQLite)。所以你可以这样做:
from django.db.models import Model, Q, UniqueConstraint
class Post(Model):
...
class Meta:
constraints = [
UniqueConstraint(fields=["title", "blog", "category"], condition=Q(category__isnull=False)),
UniqueConstraint(fields=["title", "blog"], condition=Q(category__isnull=True)),
]
Django 2.1及更早版本
在旧版本中,您需要通过迁移执行此操作。首先创建一个新的空迁移文件:
python manage.py makemigrations --empty yourappname
然后,为每个索引添加一个适当的RunSQL
行:
operations = [
migrations.RunSQL("CREATE UNIQUE INDEX..."),
migrations.RunSQL("CREATE UNIQUE INDEX..."),
]
最后,运行migrate
。
答案 1 :(得分:0)
你可以这样提供unique_together
:
class Post(models.Model):
title = models.CharField(max_length=200)
blog = models.ForeignKey(Blog)
category = models.ForeignKey(Category, null=True, blank=True)
class Meta:
unique_together = ("title", "blog", "category")
类别的NULL将按照你想要的方式工作,如果没有设置,那么title / blog必须是唯一的。
https://docs.djangoproject.com/en/1.8/ref/models/options/#unique-together