Абстрактная модель Django + миграция БД: тесты бросают "невозможно ALTER TABLE, потому что у нее есть ожидающие триггерные события"

Я хочу написать миксин абстрактной модели, который я могу использовать для создания OneToOne - отношений с моделью пользователя. Вот мой код:

from django.conf import settings
from django.db import models


class Userable(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE
    )

    class Meta:
        abstract = True

Я написал для этой модели следующий тест:

class TestUserable(TestCase):

    mixin = Userable

    def setUp(self):
        user = User.objects.create_user(
            email = "[email protected]",
            name = "Test User",
            password = "test1234test"
        )
        self.user = user
        self.model = ModelBase(
            '__TestModel__' + self.mixin.__name__, (self.mixin,),
            {'__module__': self.mixin.__module__}
        )

        with connection.schema_editor() as schema_editor:
            schema_editor.create_model(self.model)

    def test_user(self):
        self.model.objects.create(user=self.user)
        self.assertEqual(self.model.objects.count(), 1)

    def tearDown(self):
        with connection.schema_editor() as schema_editor:
            schema_editor.delete_model(self.model)

Моя проблема в том, что этот тест в методе tearDown() выдает следующую ошибку:

django.db.utils.OperationalError: cannot DROP TABLE "core___testmodel__userable" because it has pending trigger events

Что могло быть причиной этого? Я запускал python manage.py makemigrations и python manage.py migrate, но ожидающих миграций нет (как и следовало ожидать, поскольку это абстрактная модель).

Обновлено: похоже, это как-то связано с OneToOneFields или ForeignKeys (отношениями). Если я использую этот код, измененный для обычных полей, таких как CharFields или IntegerFields, он работает.

EDIT2: Если у вас есть другой лучший способ тестирования абстрактной базовой модели, использующей ForeignKeys, пожалуйста, дайте мне знать!

было бы менее запутанно, если бы вы не переназначили self.model в setUp ..

thebjorn 30.05.2018 09:55

Что вы имеете в виду? эта первая модель получает значение Userable, а затем устанавливается с помощью self.model? Я мог бы заменить первую model = Userable на mixin или что-то в этом роде :)

J. Hesters 30.05.2018 10:36
mixin сделало бы понятнее ..
thebjorn 30.05.2018 11:07

Я редактировал его, спасибо за ваше предложение. Вы знаете, как решить эту проблему?

J. Hesters 30.05.2018 11:20

К сожалению, нет, хотя меня тоже интересует ответ ..

thebjorn 30.05.2018 13:08
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
6
817
2

Ответы 2

Попробуйте код ниже. Я проверял, работает.

requirements.txt

Django==1.11.13
pkg-resources==0.0.0
pytz==2018.4

models.py

from django.conf import settings
from django.db import models


class Userable(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE
    )

    class Meta:
        abstract = True

tests.py

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.test import TestCase
from .models import Userable
from django.db import connection
from django.db.models.base import ModelBase
from django.contrib.auth.models import User


class TestUserable(TestCase):

    def setUp(self):
        user = User.objects.create_user(
            username = "[email protected]",
            password = "test1234test"
        )
        self.user = user
        self.model = ModelBase(
            Userable.__name__,
            (Userable,),
            {'__module__': Userable.__module__}
        )

        with connection.schema_editor() as schema_editor:
            schema_editor.create_model(self.model)

    def test_user(self):
        self.model.objects.create(user=self.user)
        self.assertEqual(self.model.objects.count(), 1)

    def tearDown(self):
        with connection.schema_editor() as schema_editor:
            schema_editor.delete_model(self.model)

У меня это не работает, так как я получаю версию той же ошибки: django.db.utils.OperationalError: cannot DROP TABLE "core_userable" because it has pending trigger events . Я использую нестандартную модель пользователя, я не знаю, меняет ли это что-нибудь.

J. Hesters 31.05.2018 09:02

попробуйте sql что-то вроде UPDATE foo SET bar = '' WHERE bar IS NULL в таблице базы данных <your table instead foo> со столбцом <your column instead bar>

anjaneyulubatta505 31.05.2018 09:44

Это не сработает, поскольку Userable является абстрактным и, следовательно, не имеет соответствующей миграции SQL.

J. Hesters 04.06.2018 23:35

Обычной практикой тестирования абстрактных моделей является создание реальных моделей только для тестов.

вот пример в проекте model-utilshttps://github.com/jazzband/django-model-utils/blob/master/tests/test_models/test_timestamped_model.py

from tests.models import UserableTest

class TestUserable(TestCase):
    def setUp(self):
        user = User.objects.create_user(
            email = "[email protected]",
            name = "Test User",
            password = "test1234test"
        )
        self.user = user

    def test_user(self):
        UserableTest.objects.create(user=self.user)
        self.assertEqual(UserableTest.objects.count(), 1)

В этом проекте у них отдельные настройки DJANGO_SETTINGS_MODULE = tests.settingshttps://github.com/jazzband/django-model-utils/blob/master/tests/settings.py

INSTALLED_APPS = (
    'model_utils',
    'tests',
)
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3'
    }
}
SECRET_KEY = 'dummy'

А модели описаны в https://github.com/jazzband/django-model-utils/blob/master/tests/models.py

from myapp.models import Userable

class UserableTest(Userable):
    pass

Я пробовал это решение. Я чувствую, что это может сработать. Вот что я сделал: я создал тестовое приложение в core / tests. Итак, core / tests / testapp. Затем я добавил settings.py, который наследуется от base.py и local.py. Я пробовал makemigrations, но ничего не перенесено. Я тоже получаю ошибку: psycopg2.ProgrammingError: relation "core_userabletest" does not exist.

J. Hesters 04.06.2018 23:36

@ J.Hesters, как вы проводите тесты?

Sardorbek Imomaliev 05.06.2018 02:11
python manage.py test, а затем название тестируемого приложения.
J. Hesters 06.06.2018 08:49

Назначил вам награду, потому что кажется, что она ближе всего к правильной, но я все еще не мог решить с ней свою проблему :(

J. Hesters 06.06.2018 08:50

Другие вопросы по теме