Django 2.0: sqlite IntegrityError: ограничение FOREIGN KEY не удалось

Я работаю над добавлением поддержки Django 2.0 в библиотеку django-pagetree. Во время автоматического тестирования с использованием базы данных sqlite в памяти я получаю кучу ошибок, подобных этому:

  File "/home/nnyby/src/django-pagetree/pagetree/tests/test_models.py", line 638, in setUp
    'children': [],
  File "/home/nnyby/src/django-pagetree/pagetree/models.py", line 586, in add_child_section_from_dict

...

  File "/home/nnyby/src/django-pagetree/venv/lib/python3.5/site-packages/django/db/backends/base/base.py", line 239, in _commit
    return self.connection.commit()
django.db.utils.IntegrityError: FOREIGN KEY constraint failed

Это отмечено в примечаниях к выпуску Django 2.0: https://docs.djangoproject.com/en/2.0/releases/2.0/#foreign-key-constraints-are-now-enabled-on-sqlite

Из этого описания, которое я не совсем понимаю, это не должно применяться к тестовым базам данных, которые не являются постоянными, верно? Разве моя тестовая база данных sqlite не будет создана с соответствующими параметрами при использовании Django 2.0?

Настройки приложения, которые я использую для тестирования, находятся здесь: https://github.com/ccnmtl/django-pagetree/blob/master/runtests.py


person nnyby    schedule 03.12.2017    source источник


Ответы (8)


В документации говорится о двух вещах:

  1. Если у вас есть ограничения ForeignKey, теперь они применяются на уровне базы данных. Поэтому убедитесь, что вы не нарушаете ограничение внешнего ключа. Это наиболее вероятная причина вашей проблемы, хотя это означало бы, что вы видели эти проблемы с другими базами данных. Ищите такие шаблоны в своем коде:

    # in pagetree/models.py, line 810
    @classmethod
    def create_from_dict(cls, d):
        return cls.objects.create()  # what happens to d by the way?
    

    Это определенно не удастся с ошибкой ограничения ForeignKey, поскольку PageBlock должно иметь section, поэтому вы не можете вызвать create без предварительного назначения его.

  2. Если вы обходите ограничение внешнего ключа, выполняя атомарную транзакцию (например), чтобы отложить фиксацию внешнего ключа, ваш внешний ключ должен быть ПЕРВОНАЧАЛЬНО ОТЛОЖЕН. Действительно, ваша тестовая база данных уже должна иметь это, поскольку она каждый раз перестраивается.

person dirkgroten    schedule 03.12.2017
comment
Спасибо за внимание, и я думаю, вы нашли здесь ошибку — d следует передать cls.objects.create(). - person nnyby; 03.12.2017

Встречал немного другую ситуацию с той же ошибкой. Проблема заключалась в том, что я использую одно и то же имя модели и имя поля

НЕВЕРНЫЙ КОД

class Column(models.Model):
    ...

class ColumnToDepartment(models.Model):
    column = models.ForeignKey(Column, on_delete=models.CASCADE)

СУЛЬТАЦИЯ

class Column(models.Model):
    ...

class ColumnToDepartment(models.Model):
    referring_column = models.ForeignKey(Column, on_delete=models.CASCADE)
person Yuriy Gyerts    schedule 29.05.2019
comment
Это действительно помогло мне! Я был в полной растерянности, пока не увидел этот ответ... То, как Django работает с многотабличным наследованием, подразумевает введение нескольких атрибутов в иерархию классов, соответствующих пониженным именам ваших подклассов. Если вы не знаете об этом, это может заставить вас думать, что ваш код имеет странное поведение. - person Yahya Abou Imran; 11.07.2021

У вас есть добавление on_delete к вашему FOREIGN KEY? В Django 2.0 этот аргумент обязателен. Вы также можете увидеть: https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey.on_delete https://docs.djangoproject.com/en/2.0/howto/upgrade-version/ https://docs.djangoproject.com/en/2.0/topics/db/examples/many_to_one/ https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey

person Krzysieqq    schedule 03.12.2017
comment
Да, в моем файле модели и миграции, поэтому я не думаю, что проблема в этом. Если вам интересно, моя текущая разница с django 2.0 находится здесь: github.com/ ccnmtl/django-pagetree/pull/187/файлы - person nnyby; 03.12.2017
comment
Этот действительно помог мне. У меня были атрибуты on_delete, установленные на DO_NOTHING, что привело к нарушению ограничений внешнего ключа. Установка его на SET_NULL исправила это для меня. - person Kim Palao; 18.09.2019

У меня только что была эта ошибка: sqlite3.IntegrityError: FOREIGN KEY constraint failed в моем проекте Django. Оказывается, я где-то удалил папку миграции, чтобы она не улавливала изменения моей модели, когда я запускал python manage.py makemigrations. Просто убедитесь, что у вас все еще есть папка с миграциями.

person Bennie van Eeden    schedule 22.07.2019

Еще одна вещь, которую нужно проверить, в моем случае это было связано с моими файлами фикстур. Их регенерация после перехода на Django3 решила проблему, возникшую при тестировании моего приложения.

./manage.py dumpdata app.Model1 app.Model2 --indent=4 > ./app/fixtures/file.json
person Theo Godard    schedule 01.01.2020

В моем случае я обнаружил, что объект ForeignKey, на который ссылается моя модель, не существует. Так что я просто меняю указанный объект FK на существующий объект.

person Lê Hoàng Vũ    schedule 18.06.2020

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

  1. Прокомментируйте свои строки проблем;
  2. Выполните python3 manage.py makemigrations и python3 manage.py migrate;
  3. Тогда ты должен сделать python3 manage.py migrate --fake;
  4. Раскомментируйте свои строки и сделайте это снова python3 manage.py makemigrations и python3 manage.py migrate.

Я надеюсь, что это полезно для вас

person Block2busted    schedule 09.04.2020

Моя проблема была решена после выполнения миграции, потому что я изменил внешний ключ, а затем не применил миграции.

Конкретно у меня сначала в моделях есть следующий кусок кода:

class TeacherRequest(models.Model):
    requester = models.ForeignKey(
        Profile,
        on_delete=models.CASCADE,
        related_name="teacher_request",
    )

    class RequestStatus(models.TextChoices):
        PENDING = '1', _('pending')
        APPROVED = '2', _('approved')
        REJECTED = '3', _('rejected')

    status = models.CharField(
        choices=RequestStatus.choices,
        max_length=1,
        default=RequestStatus.PENDING,
    )

Затем я изменил внешний ключ с Profile на User:


class TeacherRequest(models.Model):
    requester = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="teacher_request",
    )

    class RequestStatus(models.TextChoices):
        PENDING = '1', _('pending')
        APPROVED = '2', _('approved')
        REJECTED = '3', _('rejected')

    status = models.CharField(
        choices=RequestStatus.choices,
        max_length=1,
        default=RequestStatus.PENDING,
    )

Решение

python manage.py makemigrations
python manage.py migrate
person Mostafa Ghadimi    schedule 20.01.2021