9

用于Django 1.7的documentation提及RunSQL类可用于在表上创建部分索引。我有一张桌子,我希望title,blog & category的组合是唯一的。但是,如果没有提供类别,标题&的组合应该仍然是唯一的。用Django 1.7创建部分索引

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; 

回答

16

首先创建一个新的空迁移文件:

python manage.py makemigrations --empty yourappname 

然后,对每个指标添加适当的RunSQL行:

operations = [ 
    migrations.RunSQL("CREATE UNIQUE INDEX..."), 
] 

最后,运行migrate

+0

谢谢。我无法在文档中找到它。何时以及如何使用'sql'&'reverse_sql'参数? – user4150760 2014-10-17 04:04:51

+1

@ user4150760:'sql'参数是创建索引的字符串,就像您在上面给出的一样。如果您希望能够回滚迁移,请提供'reverse_sql'参数。在这种情况下,这将是等效的“DROP INDEX ...”命令。 'state_operations'参数在这里不适用。 – 2014-10-17 05:33:52

1

你可以只提供一个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") 

空值的类别将工作你想怎么在如果没有设置则标题/博客必须是唯一的。

https://docs.djangoproject.com/en/1.8/ref/models/options/#unique-together

+0

您链接的文档既不支持也不驳斥您所说的内容。某些(所有?)数据库从不等于空值(即,一列空值满足它的唯一约束),因此如果标题,博客或类别中的任何一个为空,那么unique_together子句将得到平凡满足。 – DylanYoung 2016-11-02 16:03:47

+0

unique_together不适用于条件索引,只是多键索引 – 2017-04-19 13:57:05