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

J. *_*ers 8 django django-models django-testing django-tests django-migrations

我想编写一个抽象模型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
Run Code Online (Sandbox Code Playgroud)

我为这个模型编写了以下测试:

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)
Run Code Online (Sandbox Code Playgroud)

我的问题是,在它的tearDown()方法中的这个测试抛出了以下错误:

django.db.utils.OperationalError: cannot DROP TABLE "core___testmodel__userable" because it has pending trigger events
Run Code Online (Sandbox Code Playgroud)

可能是什么原因造成的?我没有跑python manage.py makemigrationspython manage.py migrate,但没有挂起的迁移(如预期,因为这是一个抽象的模型).

编辑:它似乎与OneToOneFields或ForeignKeys(关系)有关.如果我使用此代码更改为常规字段,如CharFields或IntegerFields,它的工作原理.

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

anj*_*505 0

尝试下面的代码。我已经测试过它可以工作。

要求.txt

Django==1.11.13
pkg-resources==0.0.0
pytz==2018.4
Run Code Online (Sandbox Code Playgroud)

模型.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
Run Code Online (Sandbox Code Playgroud)

测试.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)
Run Code Online (Sandbox Code Playgroud)