Абстрактная модель Django + миграция БД: тесты выдают «ALTER TABLE не может, потому что у него есть ожидающие события триггера» - PullRequest
0 голосов
/ 27 мая 2018

Я хочу написать микс абстрактной модели, который я могу использовать для создания 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="testuser@test.com",
            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, пожалуйста, дайте мне знать!

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

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

, вот пример в model-utils проекте https://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="testuser@test.com",
            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.settings https://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
0 голосов
/ 30 мая 2018

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

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="testuser@test.com",
            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)
...