使用Django 1.7创建部分索引

时间:2014-10-16 17:32:45

标签: django django-models django-orm django-1.7 django-migrations

Django 1.7的documentation提及RunSQL类可用于在表上创建部分索引。我有一张表格,我想要titleblog& 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;

2 个答案:

答案 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