2013-07-13 35 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), 
    ]