2013-07-13 53 views
22

這是Django的文檔:Django的獨特=真不工作

Field.unique

If True, this field must be unique throughout the table.

This is enforced at the database level and by model validation. If you try to save a model with a duplicate value in a unique field, a django .db.IntegrityError will be raised by the model’s save() method.

這裏是我的models.py

class MyModel(models.Model): 
    # my pk is an auto-incrementing field 
    url = models.URLField("URL", unique=True) 
    text = models.TextField(max_length=1000) 
    # my model is just two fields, one pk (unique), and another unique field, 
    #, the url 

這裏我是manage.py sqlall(我跑了執行syncdb)

CREATE TABLE `MyModel_mymodel` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, 
    `url` varchar(200) NOT NULL UNIQUE, 
    `text` varchar(1000) NOT NULL, 

但是,在manage.py shell中,我可以自由地做到這一點:

>>> from MyModel.models import MyModel 
>>> MyModel().save() # it works fine!? Not even the text was checked for! 
>>> MyModel(url="blah").save() 
>>> MyModel(url="blah").save() # it still works! 

# I checked the mysql database afterwards, the models were saved just fine, they 
# however did have different PK's (auto incrementing fields). 

我使用的是mysql,django 1.5。有沒有人有一個想法有可能造成這種情況?

我正在使用自定義管理器,但我懷疑這是問題所在。

謝謝。

+0

我'IntegrityError:列網址是不是第二個'爲MyModel(URL = 「嗒嗒」)unique'例外保存()'。你是否按原樣粘貼了你的代碼? – falsetru

+0

'text'字段定義有錯字..'模式'。我懷疑你沒有複製和粘貼你的代碼。 – falsetru

+0

不,我不認爲代碼需要張貼,只有兩個領域值得注意 –

回答

34

Django的1.9+
運行makemigrations然後migrate適用的唯一約束SQLITE3

Django的< 1.9
由於您使用的Django 1.5,該解決方案將適用。

如果您在創建表後添加了unique=True,那麼即使稍後再執行syncdb,唯一條件也不會添加到您的表中。

我可以通過sqlite3確認Django 1.5如果數據庫中不存在唯一的約束條件,並且與文檔相矛盾,那麼我們很高興地將重複的對象與MyModel(url="blah").save()保存在一起。

最適合您的解決方案是使用此命令在數據庫中手動創建約束。

ALTER TABLE MyModel_mymodel ADD UNIQUE (url); 

或者,如果您不介意,您可以重新創建表格。 (刪除表,然後運行syncdb。)

+0

謝謝,它的工作原理。我希望django在很多這種數據庫的東西上更容易,比如更改和刪除FK等。 –

+10

使用[South](http://south.aeracode.org/)進行模式遷移。 – Matthias

+3

使用django 1.9.4將獨特的條件添加到表中(使用sqlite3) - 即使表已經創建。 –

0

直接在db上運行sql腳本可以避免。而是添加SQL執行的遷移:

from __future__ import unicode_literals 
from django.db import migrations, connection 


def alter_table(apps, schema_editor): 
    query ="ALTER TABLE <your table> ADD UNIQUE (unique_col);" 
    cursor = connection.cursor() 
    cursor.execute(query) 
    cursor.close() 

class Migration(migrations.Migration): 

    dependencies = [ 
     ('app', 'yourlastmigration'), 
    ] 

    operations = [   
     migrations.RunPython(alter_table), 
    ]