您的表是非托管的 (managed = False),因此不会在迁移或测试期间自动创建。
- 如果您的表应该在迁移期间创建,只需删除
managed = False 行
- 如果您的表是不应在迁移期间创建的视图或旧表,则需要在测试期间管理模型。
如果 2,并且您使用的是简单的 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 进行测试,而上面的解决方案停止工作。经过大量搜索后,我在 cmets 中发现了对上述示例中的其中一个页面的修复 (source, credit to 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 中,我们的测试又开始工作了。