您的表是非托管的 ( managed = False
),因此它不会在迁移或测试期间自动创建。
- 如果您的表应该在迁移期间创建,只需删除该
managed = False
行
- 如果您的表是不应在迁移期间创建的视图或旧表,则需要在测试期间管理模型。
如果 2,并且您使用的是 simple manage.py test
,我发现的最佳解决方案是添加一个测试运行程序,该运行程序可以修改任何非托管模型上的托管标志。我的在 runners.py 文件中看起来像这样:
# Credit:
# http://birdhouse.org/blog/2015/03/25/django-unit-tests-against-unmanaged-databases/
# https://www.caktusgroup.com/blog/2010/09/24/simplifying-the-testing-of-unmanaged-database-models-in-django/
from smapi.settings import *
from django.test.runner import DiscoverRunner
class ManagedModelTestRunner(DiscoverRunner):
"""
Test runner that automatically makes all unmanaged models in your Django
project managed for the duration of the test run, so that one doesn't need
to execute the SQL manually to create them.
"""
def __init__(self, **kwargs):
from django.apps import apps
super(ManagedModelTestRunner, self).__init__(**kwargs)
# for a in apps.get_apps():
# print("Found app %s" % (a))
# NOTE: apps must be registered in INSTALLED_APPS in settings.py before their models appear here
all_models = apps.get_models()
# for m in all_models:
# print("Found model %s - Managed:%s" % (m, m._meta.managed))
self.unmanaged_models = [m for m in all_models if not m._meta.managed]
def setup_test_environment(self, *args, **kwargs):
for m in self.unmanaged_models:
m._meta.managed = True
# print("Modifying model %s to be managed for testing - Managed:%s" % (m, m._meta.managed))
super(ManagedModelTestRunner, self).setup_test_environment(*args, **kwargs)
def teardown_test_environment(self, *args, **kwargs):
super(ManagedModelTestRunner, self).teardown_test_environment(*args, **kwargs)
# reset unmanaged models
for m in self.unmanaged_models:
m._meta.managed = False
# print("Resetting model %s to be unmanaged - Managed:%s" % (m, m._meta.managed))
通过将此行添加到 settings.py 来激活它:
# Set Django's test runner to the custom class defined in runners.py
TEST_RUNNER = '<project name>.runners.ManagedModelTestRunner'
最后,我今天来到这里是因为我们开始使用 pytest 进行测试,而上面的解决方案停止了工作。经过大量搜索,我在上面示例中的一个页面的评论中发现了一个修复(来源,归功于 Jan Murre)
谢谢你的把戏。因为我使用的是 pytest-django,所以我必须找出如何以我的方式做到这一点。
pytest-django 使用固定装置。已经有一个夹具可以执行 setup_test_environment() 调用。
因此,我们需要一个在此之前的夹具来设置“_meta.managed”。似乎自动夹具是按字母顺序执行的,所以在 pytest-django 夹具(名称以“_django”开头)之前,我们的夹具名称以“__”开头。
@pytest.fixture(autouse=True, scope='session')
def __make_unmanaged_managed():
from django.db.models.loading import get_models
unmanaged_models = [m for m in get_models() if not m._meta.managed]
for m in unmanaged_models:
m._meta.managed = True
我们将上面的代码放在 conftest.py 中,我们的测试又开始工作了。