如何在使用managed = False的Django测试期间创建表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在使用managed = False的Django测试期间创建表相关的知识,希望对你有一定的参考价值。

我有一个托管= 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 docs - https://docs.djangoproject.com/en/dev/ref/models/options/#managed记录了以下内容:

对于涉及托管= False的模型的测试,由您来确保在测试设置中创建正确的表。

如何在测试设置期间实际“创建”表格?或者,我怎样才能使它在运行测试时,在测试期间该模型具有“managed = True”?

在实际应用程序中,此模型实际上由数据库中的视图支持。但是对于测试期间,我想将其视为一个表,并能够在那里插入测试数据。

答案

看看这篇博客文章: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
另一答案

执行原始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 ...")
另一答案

使用以下方法创建自己的测试运行器

from django.test.simple import DjangoTestSuiteRunner

class NoDbTestRunner(DjangoTestSuiteRunner):
  """ A test runner to test without database creation """

  def setup_databases(self, **kwargs):
    """ Override the database creation defined in parent class """
    #set manage=True for that specific database on here

然后在您的设置上将此类添加到TEST_RUNNER。

另一答案

如果您没有许多非托管表,请快速修复:

首先在设置中添加一个新变量。

# settings.py
import sys
UNDER_TEST = (len(sys.argv) > 1 and sys.argv[1] == 'test')

然后在模型中

# models.py
from django.conf import settings

class SampleModel(models.Model):
    apple = models.CharField(max_length=30)
    orange = models.CharField(max_length=30)

    class Meta:
        managed = getattr(settings, 'UNDER_TEST', False)
另一答案

不错的即插即用解决方案。只需在测试类定义之前粘贴它即可。 (注意:使用django 1.8)

from django.db.models.loading import get_models

def change_managed_settings_just_for_tests():
  """django model managed bit needs to be switched for tests."""    

  unmanaged_models = [m for m in get_models() if not m._meta.managed]
  for m in unmanaged_models:
    m._meta.managed = True

change_managed_settings_just_for_tests()
另一答案

只需添加:django.db.models.loading.get_models将在Django 1.9中删除(参见https://github.com/BertrandBordage/django-cachalot/issues/33)。

下面是Django 1.10的更新版本:

class UnManagedModelTestRunner(DiscoverRunner):
    '''
    Test runner that automatically makes all unmanaged models in your Django
    project managed for the duration of the test run.
    Many thanks to the Caktus Group 
    '''

    def setup_test_environment(self, *args, **kwargs):
        from django.apps  import apps
        self.unmanaged_models = [m for m in apps.get_models() if not m._meta.managed]
        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 unmanaged models
        for m in self.unmanaged_models:
            m._meta.managed = False 

请注意,您还需要注意迁移(请参阅Testing django application with several legacy databases

MIGRATION_MODULES = {
    'news': 'news.test_migrations',
    'economist': 'economist.test_migrations'
}
另一答案

您可以在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())

以上是关于如何在使用managed = False的Django测试期间创建表的主要内容,如果未能解决你的问题,请参考以下文章

如何使用JVisualVM进行性能分析

在以下任何来源中均未找到插件[id:'io.spring.dependency-management',版本:'1.0.5.RELEASE',apply:false]:

如何在托管 = False 的 Django 测试期间创建表?

./manage.py 对 Django 1.4 的测试给出了在 google appengine 上找不到的 Thing2Literal 导入

django2.2 DEBUG=True/False时如何设置静态文件(image js css等)

如何在 Java VisualVM 中显示探查器选项卡? [复制]