Как воспроизвести следующую IntegrityError в модульном тесте django? - PullRequest
0 голосов
/ 06 апреля 2019

У меня есть две модели «Вопрос» и «Шрифт».В этих «Вопросах» есть не удаляемая модель.И у Вопроса есть ссылка на Шрифт.

Так что, если шрифт удален, тогда ссылка на шрифт, о которой идет речь, будет установлена ​​равной нулю, а если вопрос будет удален, то, поскольку вопрос является не удаляемой моделью, он не будетПри удалении из БД его активное поле будет установлено в False, поэтому его нельзя запросить через менеджер моделей объектов Django.В этом случае, если я удаляю вопрос и после этого, если я пытаюсь удалить шрифт, он выдает «IntegrityError», так как мягкий удаленный вопрос по-прежнему имеет ссылку на шрифт.

Проблема в том, что я не могув состоянии воспроизвести это в модульном тесте.В модульном тесте шрифт удаляется изящно.В веб-интерфейсе я получаю следующее.

update or delete on table "custom_fonts_customfont" violates foreign key constraint "font_id_refs_id_794a5361" on table "questions_question"
DETAIL:  Key (id)=(1026) is still referenced from table "questions_question".

Я пытался использовать тестовый пример Django Transaction, я также удостоверился, что вопрос мягко удален в тестовом примере, и подтвердил ссылку вопроса на шрифт, используя Django's неотфильтрованныймодель менеджер.

class Question(ExtendedOrderedModel, NonDeletableModel):
      font = models.ForeignKey('custom_fonts.CustomFont', null=True, on_delete=models.SET_NULL)

Это мой тестовый пример

    def test_font_deletion_after_question_deletion_(self):
        self.question.font = CustomFont.objects.create(
            name='roboto', font_type='truetype', path='font.ttf', created_by=self.owner
        )
        self.question.save()
        self.question.delete()

        CustomFont.objects.all().delete() # This should raise an error but it is not raising

        print(Question.objects.all()) # []
        print(Question.unfiltered.first().font_id) # 1

1 Ответ

0 голосов
/ 30 апреля 2019

Наконец-то я нашел причину.Это потому, что

В Postgresql ограничения установлены DEFERRABLE INITIALLY DEFERRED.Это заставляет его проверять только те ограничения, когда транзакция зафиксирована.(Это также может повлиять на серверную часть Oracle, основываясь на быстром поиске.) Это вызывает проблему с TestCase: поскольку они никогда не фиксируются, многие нарушения ограничений никогда не могут быть инициированы.

Добавлениемне помогли следующие строки в моем тестовом примере.

cursor = connection.cursor()
cursor.execute('SET CONSTRAINTS ALL IMMEDIATE')

source: https://code.djangoproject.com/ticket/11665

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...