如何在Django测试中创建managed=False的表格
我有一个模型,它的设置是 managed = False。
class SampleModel(models.Model):
apple = models.CharField(max_length=30)
orange = models.CharField(max_length=30)
class Meta:
managed = False
我有一个单元测试,它会创建一个 SampleModel,但当我运行这个测试时,我得到了:
DatabaseError: no such table: SAMPLE_SAMPLE_MODEL
根据 Django 的文档 - https://docs.djangoproject.com/en/dev/ref/models/options/#managed,有以下说明:
对于涉及 managed=False 的模型的测试,你需要自己确保在测试准备阶段创建正确的表。
那么我该如何在测试准备阶段“创建”这些表呢?或者,如何才能让这个模型在运行测试时变成“managed = True”,在测试期间使用?
在实际应用中,这个模型实际上是由数据库中的一个视图支持的。不过在测试期间,我希望把它当作一个表来使用,并能够在里面插入测试数据。
10 个回答
8
在测试环境中执行原始SQL语句来创建表:
from django.db import connection
class MyTest(unittest.TestCase):
def setUp(self):
connection.cursor().execute("CREATE TABLE ...")
def tearDown(self):
connection.cursor().execute("DROP TABLE ...")
18
你可以在SchemaEditor中使用TestCase.setUp
方法,来明确地创建一些模型,并设置它们为managed = False
。
# models.py
from django.db import models
class Unmanaged(models.Model):
foo = models.TextField()
class Meta:
# This model is not managed by Django
managed = False
db_table = 'unmanaged_table'
然后在你的测试中:
# tests.py
from django.db import connection
from django.test import TestCase
from myapp.models import Unmanaged
class ModelsTestCase(TestCase):
def setUp(self):
super().setUp()
with connection.schema_editor() as schema_editor:
schema_editor.create_model(Unmanaged)
if (
Unmanaged._meta.db_table
not in connection.introspection.table_names()
):
raise ValueError(
"Table `{table_name}` is missing in test database.".format(
table_name=Unmanaged._meta.db_table
)
)
def tearDown(self):
super().tearDown()
with connection.schema_editor() as schema_editor:
schema_editor.delete_model(Unmanaged)
def test_unmanaged_model(self):
with self.assertNumQueries(num=3):
self.assertEqual(0, Unmanaged.objects.all().count())
Unmanaged.objects.create()
self.assertEqual(1, Unmanaged.objects.all().count())
16
看看这篇博客文章:http://www.caktusgroup.com/blog/2010/09/24/simplifying-the-testing-of-unmanaged-database-models-in-django/ 里面详细讲解了如何为不受管理的模型创建一个测试运行器。
from django.test.simple import DjangoTestSuiteRunner
class ManagedModelTestRunner(DjangoTestSuiteRunner):
"""
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 setup_test_environment(self, *args, **kwargs):
from django.db.models.loading import get_models
self.unmanaged_models = [m for m in get_models()
if not m._meta.managed]
for m in self.unmanaged_models:
m._meta.managed = True
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