Django抽象模型+数据库迁移:测试抛出"不能ALTER TABLE,因为它有待处理的触发事件"

时间:2018-05-27 14:17:42

标签: django django-models django-testing django-migrations django-tests

我想编写一个抽象模型mixin,我可以使用它来创建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 makemigrationspython manage.py migrate,但没有待定的迁移(正如预期的那样,因为这是一个抽象模型)。

编辑:它似乎与OneToOneFields或ForeignKeys(关系)有关。如果我使用这个代码改为常规字段,比如CharFields或IntegerFields,它就可以工作。

EDIT2:如果你有另一种更好的方法来测试使用ForeignKeys的抽象基础模型,请告诉我!

2 个答案:

答案 0 :(得分:0)

尝试以下代码。我已经测试过它正在运行。

  

requirements.txt

String s1 = "l'épargne";
String s2 = new String(s1.getBytes("iso-8859-1"), "utf8");
  

models.py

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

tests.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

答案 1 :(得分:0)

测试抽象模型的常用做法是为测试创建实际模型

此处是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