Подтвердить что ты не робот

Django unique = True не работает

Это из документации django:

Field.unique

Если True, это поле должно быть уникальным по всей таблице.

Это выполняется на уровне базы данных и путем проверки модели. Если вы попытаетесь сохранить модель с двойным значением в уникальном поле, django.db.IntegrityError будет поднят методом save().

Вот мои 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

Здесь мой is 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 я могу свободно это делать:

>>> 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 (auto incrementing fields).

Я использую mysql, django 1.5. Кто-нибудь есть идея, что может быть причиной этого?

Я использую настраиваемый менеджер, но я сомневаюсь, что проблема.

Спасибо.

4b9b3361

Ответ 1

Для 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.)

Ответ 2

Можно запускать скрипты sql непосредственно на db. Скорее добавьте выполнение 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),
    ]