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