django не вызывает IntegrityError для дубликата первичного ключа

Обеспечивает ли django уникальность первичного ключа?

Документация здесь выглядит предложить так, но когда я определяю класс как:

class Site(models.Model):
    id = models.IntegerField(primary_key=True)

и проверьте это ограничение в тестовом примере:

class SiteTestCase(TestCase):
    def setUp(self):
        self.site = Site(id=0, name='Site')
        self.site.save()

    def tearDown(self):
        self.site.delete()

    def test_unique_id(self):
        with self.assertRaises(IntegrityError):
            badSite = Site(id=0, name='Bad Site')
            badSite.save()
            badSite.delete()

тест не проходит.

Если я проверяю нормальное поле (primary_key=False, unique=True), то исключение возникает правильно. Установка unique=True в поле id не меняет результат.

Есть ли что-то в полях primary_key, которые мне здесь не хватает?

Моя база данных — это MySQL, если это уместно.


person sapi    schedule 22.01.2013    source источник


Ответы (1)


Ваш метод тестирования неверен. Здесь вы обновляете существующий экземпляр, поскольку вы предоставляете уже используемый первичный ключ. Измените save на force_insert вот так.

def test_unique_id(self):
        with self.assertRaises(IntegrityError):
            badSite = Site(id=0, name='Bad Site')
            badSite.save(force_insert=True)
            badSite.delete()

Документы django объясняют, как django знает, следует ли ОБНОВИТЬ или ВСТАВИТЬ. Вы должны прочитать этот раздел.

Вы знаете, что django уже поддерживает автоматические первичные ключи? Дополнительные сведения см. в документации. объяснение.

person Josh Smeaton    schedule 22.01.2013
comment
Я знаю, что поле автоматического первичного ключа называется id, но поскольку id имеет реальное значение в этом контексте, я хочу установить его вручную. Добавление unique=True к определению не обеспечивает уникальность (я уже пробовал это). Я отредактирую вопрос, чтобы отразить это. - person sapi; 23.01.2013
comment
@sapi, я понял, что мой первый ответ был неправильным. Я обновил соответственно. - person Josh Smeaton; 23.01.2013
comment
Спасибо, разобрался. Лично я нахожу это поведение довольно странным (я ожидаю, что каждый вызов конструктора модели создаст новый экземпляр/строку и обновит его только в том случае, если я получил доступ к существующей модели из базы данных), но оно четко определено, поэтому мой ошибка. - person sapi; 23.01.2013
comment
@sapi, это означало бы, что вам нужно будет сделать выбор, даже если у вас уже есть детали из другого места (что довольно часто встречается в большинстве случаев). Однако за последний месяц я ответил здесь на два вопроса, у которых было то же предположение, что и у вас. Я нахожу поведение хорошим для подавляющего большинства случаев. - person Josh Smeaton; 23.01.2013