我有使用非托管(只读)模型的mutlidb设置。这些模型没有迁移。我正在尝试测试view.py的功能。在sqlite3数据库中,测试表的这些架构不会在导致测试用例失败的过程中引起问题。 在view.py中,我导入了非托管(只读)模型失败。
我已经点击了测试链接Testing against unmanaged models
提到了多数据库设置
from django.test.runner import DiscoverRunner
class DisableMigrations(object):
def __contains__(self, item):
return True
def __getitem__(self, item):
return None
class UnManagedModelTestRunner(DiscoverRunner):
def setup_test_environment(self, *args, **kwargs):
from django.apps import apps
# app_name = apps.get_app_config('core_esp')
self.unmanaged_models = [m for m in apps.get_models() if not m._meta.managed and m._meta.app_label is 'core_esp']
for m in self.unmanaged_models:
m._meta.managed = True
super(UnManagedModelTestRunner, self).setup_test_environment(*args, **kwargs)
def teardown_test_environment(self, *args, **kwargs):
super(UnManagedModelTestRunner, self).teardown_test_environment(*args, **kwargs)
# reset un managed models
for m in self.unmanaged_models:
m._meta.managed = False
if 'test' in sys.argv or 'test_coverage' in sys.argv:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'db.sqlite3',
},
'test_db': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'db.sqlite3',
}
}
INSTALLED_APPS = ['test']
# Skip the migrations by setting "MIGRATION_MODULES"
# to the DisableMigrations class defined above
#
MIGRATION_MODULES = DisableMigrations()
# Set Django's test runner to the custom class defined above
TEST_RUNNER = 'apps.settings.test_runner.UnManagedModelTestRunner'
DATABASE_ROUTERS = ('apps.tests.test_dbrouter.TestApiRouter', )
from django.db import models
class TestModelA(models.Model):
testid = models.CharField(max_length=200)
class Meta:
managed = False
db_table = 'TestD'
class TestModelB(models.Model):
testid = models.CharField(max_length=200)
class Meta:
managed = False
db_table = 'test_model_b'
app_label = 'application_b'
class MyTestCase(TestCase):
def test_my_function(self):
# view is called
# serializer called with read only model
pass
Traceback (most recent call last):
File "C:\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\lib\site-packages\django\db\backends\sqlite3\base.py", line 383, in execute return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such table: TestD
The above exception was the direct cause of the following exception: Traceback (most recent call last):
File "manage.py", line 21, in <module> main()
File "manage.py", line 17, in main execute_from_command_line(sys.argv)
File "C:\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line utility.execute()
File "C:\lib\site-packages\django\core\management\__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\lib\site-packages\django\core\management\commands\test.py", line 23, in run_from_argv
super().run_from_argv(argv)
File "C:\lib\site-packages\django\core\management\base.py", line 323, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\lib\site-packages\django\core\management\base.py", line execute
output = self.handle(*args, **options)
File "C:\lib\site-packages\django\core\management\commands\test.py", line 53, in handle failures = test_runner.run_tests(test_labels)
File "C:\lib\site-packages\django\test\runner.py", line 627, in run_tests
suite = self.build_suite(test_labels, extra_tests)
File "C:\lib\site-packages\django\test\runner.py", line 488, in build_suites
tests = self.test_loader.loadTestsFromName(label)
File "c:\program files\python37\Lib\unittest\loader.py", line 154, in loadTestsFromName
module = __import__(module_name)
File "C:\tests\tests.py", line 5, in <module>
from .views import (
File "C:\views.py", line 6, in <module>
from .serializers import (
File "C:\serializers.py", line 9, in <module>
class TestSerializer(serializers.Serializer):
File "C:\serializers.py", line 13, in TestSerializer
required=False, style={'base_template': 'select_multiple.html'}
File "C:\lib\site-packages\rest_framework\fields.py", line 1476, in __init__
super(MultipleChoiceField, self).__init__(*args, **kwargs)
File "C:\lib\site-packages\rest_framework\fields.py", line 1417, in __init__
self.choices = choices
File "C:\lib\site-packages\rest_framework\fields.py", line 1453, in _set_choices
for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):
File "C:\lib\site-packages\django\db\models\sql\compiler.py", line 1052, in results_iter
results = self.execute_sql(MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size)
File "C:\lib\site-packages\django\db\models\sql\compiler.py", line 1100, in execute_sql
cursor.execute(sql, params)
File "C:\lib\site-packages\django\db\backends\utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False,
executor=self._execute)
File "C:\lib\site-packages\django\db\backends\utils.py", line 76, in
_execute_with_wrappers
return executor(sql, params, many, context)
File "C:\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\lib\site-packages\django\db\utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\lib\site-packages\django\db\backends\sqlite3\base.py", line 383, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: TESTD
答案 0 :(得分:1)
我发现在当前的django 2.2中可以使用的很好的解决方案。可以与pytest-django完美搭配使用,但即使没有pytest也可以使用。
要使其正常运行,您需要:
将您的项目拆分为两个django应用程序。一个将仅包含非托管模型,而另一个将包含其余模型。请勿在这两个应用程序中的任何一个中指定managed = False
在DATABASES中的settings.py中,您将有两个数据库,一个是默认数据库,一个是您的外部数据库
使用pytest运行测试时,它实际上为没有迁移文件夹的应用创建了所有表
答案 1 :(得分:0)
我可以向您展示我如何解决此问题;
所以我创建了一个信号,或多或少看起来像这样:
def create_test_models(**kwargs):
if "test" in sys.argv:
Organization = apps.get_model("organizations.Organization")
... # other models here too
# as we do not manage it - we need to create it manually;
with connection.schema_editor() as schema_editor:
sid = transaction.savepoint()
try:
schema_editor.create_model(Organization)
... # different models here if needed
transaction.savepoint_commit(sid)
except ProgrammingError: # tables already exists;
transaction.savepoint_rollback(sid)
此信号作为pre_migrate
信号在配置中连接:
class OrganizationsConfig(AppConfig):
name = "engine.organizations"
def ready(self):
# run after each migration; so each deploy, but this method can handle the
# incremental updates.
pre_migrate.connect(create_test_models, sender=self)
这可能不是超级解决方案-但它正在运行,并且您在测试过程中创建了模型,您可以使用它们或创建测试数据等。
希望这将帮助您前进。