Я хочу написать миксин абстрактной модели, который я могу использовать для создания 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, пожалуйста, дайте мне знать!
Что вы имеете в виду? эта первая модель получает значение Userable, а затем устанавливается с помощью self.model? Я мог бы заменить первую model = Userable на mixin или что-то в этом роде :)
mixin сделало бы понятнее ..
Я редактировал его, спасибо за ваше предложение. Вы знаете, как решить эту проблему?
К сожалению, нет, хотя меня тоже интересует ответ ..
Возможный дубликат Django-DB-Migrations: невозможно ALTER TABLE, потому что у него есть ожидающие триггерные события





Попробуйте код ниже. Я проверял, работает.
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 . Я использую нестандартную модель пользователя, я не знаю, меняет ли это что-нибудь.
попробуйте sql что-то вроде UPDATE foo SET bar = '' WHERE bar IS NULL в таблице базы данных <your table instead foo> со столбцом <your column instead bar>
Это не сработает, поскольку Userable является абстрактным и, следовательно, не имеет соответствующей миграции SQL.
Обычной практикой тестирования абстрактных моделей является создание реальных моделей только для тестов.
вот пример в проекте 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, как вы проводите тесты?
python manage.py test, а затем название тестируемого приложения.
Назначил вам награду, потому что кажется, что она ближе всего к правильной, но я все еще не мог решить с ней свою проблему :(
было бы менее запутанно, если бы вы не переназначили self.model в
setUp..