Django在运行测试时会忽略路由器吗?

时间:2015-10-30 10:56:22

标签: python django database

我有一个使用2个数据库连接的django应用程序:

  1. 连接到应用程序要生成的实际数据
  2. 到完全不受我控制的参考主数据系统
  3. 我遇到的问题是,我的网络应用程序绝对不能触及第二个数据库中的数据。我通过使用2个(子)应用程序解决了大多数问题,每个数据库连接一个。我创建了一个路由器文件,用于路由任何迁移,并写入第一个应用程序

    我还使用

    使第二个应用中的所有模型都无法管理
    model.meta.managed = False
    

    选项。

    可以肯定的是,我连接到第二个数据库的用户具有只读访问权限

    这适用于迁移和运行。但是,当我尝试使用django testcase运行测试时,Django尝试在第二个数据库连接上删除并创建一个test_数据库。

    如何确保Django永远不会更新/删除/插入/删除/截断第二个连接

    如何运行不尝试创建第二个数据库的测试,但是创建第一个。

    谢谢!

    已编辑:代码

    模型(对于第二个应用,不应管理):

    from django.db import models
    
    
    class MdmMeta(object):
        db_tablespace = 'MDM_ADM'
        managed = False
        ordering = ['name']
    
    
    class ActiveManager(models.Manager):
        def get_queryset(self):
            return super(ActiveManager, self).get_queryset().filter(lifecyclestatus='active')
    
    
    class MdmType(models.Model):
        entity_guid = models.PositiveIntegerField(db_column='ENTITYGUID')
        entity_name = models.CharField(max_length=255, db_column='ENTITYNAME')
    
        entry_guid = models.PositiveIntegerField(primary_key=True, db_column='ENTRYGUID')
    
        name = models.CharField(max_length=255, db_column='NAME')
        description = models.CharField(max_length=512, db_column='DESCRIPTION')
    
        lifecyclestatus = models.CharField(max_length=255, db_column='LIFECYCLESTATUS')
    
        # active_manager = ActiveManager()
    
        def save(self, *args, **kwargs):
            raise Exception('Do not save MDM models!')
    
        def delete(self, *args, **kwargs):
            raise Exception('Do not delete MDM models!')
    
        def __str__(self):
            return self.name
    
        class Meta(MdmMeta):
            abstract = True
    
    
    # Create your models here.
    class MdmSpecies(MdmType):
        class Meta(MdmMeta):
            db_table = 'MDM_SPECIES'
            verbose_name = 'Species'
            verbose_name_plural = 'Species'
    
    
    class MdmVariety(MdmType):
        class Meta(MdmMeta):
            db_table = 'MDM_VARIETY'
            verbose_name = 'Variety'
            verbose_name_plural = 'Varieties'
    
    ...
    

    路由器:

    __author__ = 'CoesseWa'
    
    class MdmRouter(object):
    
        def db_for_read(self, model, **hints):
            if model._meta.app_label == 'mdm':
                # return 'default'
                return 'mdm_db'   # trying to use one database connection
            return 'default'
    
        def db_for_write(self, model, **hints):
            return 'default'
    
        def allow_relation(self, obj1, obj2, **hints):
            return None
    
        def allow_migrate(self, db, model):
            if model._meta.app_label == 'mdm':
                return False
    

    设置:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.oracle',
            'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=1521)))(CONNECT_DATA=(SID=%s)))'
                    % (get_env_variable('LIMS_MIGRATION_HOST'), get_env_variable('LIMS_MIGRATION_SID')),
            'USER': 'LIMS_MIGRATION',
            'PASSWORD': get_env_variable('LIMS_MIGRATION_PASSWORD'),
        },
        'mdm_db': {
            'ENGINE': 'django.db.backends.oracle',
            'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=GB3P)(PORT=1521)))'
                    '(CONNECT_DATA=(SID=GB3P)))',
            'USER': 'MDM',
            'PASSWORD': get_env_variable('MDM_DB_PASSWORD'),
        },
    }
    

    一个测试用例:

    from django.test.testcases import TestCase
    
    __author__ = 'CoesseWa'
    
    
    class ModelTest(TestCase):
    
        def test_getting_guid_for_mdm_field(self):
            self.assertIsNotNone(1)
    

    运行此测试时的输出:

    ... 
    Destroying old test user...
    

    (在此之前,django为我的第一个连接创建了测试数据库= OK)

    Creating test user...
    

    =>下一行不应该发生。因为我使用只读用户(幸运的是)

    而失败
    Creating test database for alias 'mdm_db'...
    
    Failed (ORA-01031: insufficient privileges 
    Got an error creating the test database: ORA-01031: insufficient privileges
    

3 个答案:

答案 0 :(得分:11)

我通过更改DATABASES.TEST定义解决了这个问题。我将TEST['MIRROR'] = 'default'添加到mdm_db数据库条目。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=1521)))(CONNECT_DATA=(SID=%s)))'
                % (get_env_variable('LIMS_MIGRATION_HOST'), get_env_variable('LIMS_MIGRATION_SID')),
        'USER': 'LIMS_MIGRATION',
        'PASSWORD': get_env_variable('LIMS_MIGRATION_PASSWORD'),
    },
    'mdm_db': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=GB3P)(PORT=1521)))'
                '(CONNECT_DATA=(SID=GB3P)))',
        'USER': 'MDM',
        'PASSWORD': get_env_variable('MDM_DB_PASSWORD'),
        'TEST': {
            'MIRROR': 'default',  # Added this setting
        }
    },
}

根据documentation,可以滥用此选项来跳过数据库创建:

  

但是,副本数据库已配置为测试镜像   (使用MIRROR测试设置),表明正在测试中,   副本应被视为默认镜像。

     

配置测试环境时,副本的测试版本   不会被创建。相反,与副本的连接将是   重定向到默认值。

现在运行我的测试会跳过第二个数据库的创建。

感谢所有输入!!

答案 1 :(得分:2)

--settings标志与test命令一起使用。在path.to.test.py模块中,la python manage.py test --settings=app.settings.test。没有必要使用路由,只需确保您随时随地调用设置标志来调用测试。

在app.settings.test.py中,重新定义您的DATABASES数据结构:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': '',
        'USER': '',
        'PASSWORD': '',
    },
    'mdm_db': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': '',
        'USER': '',
        'PASSWORD': '',
    },
}

这允许您在运行测试时使用单独的数据库。此外,如果您使用sqlite3作为引擎,您会发现测试运行得非常快,因为数据库在内存中。

使用sqlite3数据库进行测试意味着甚至可以在几秒钟内运行数百个测试。因此,您可以非常频繁地运行测试。我通常会映射一个键以保存我的工作并通过一个操作运行我的测试:

map ,t :up\|!python manage.py test --settings=app.settings.test

希望这是有帮助的!

答案 2 :(得分:0)

您可以尝试使用python模拟模拟与第二个数据库的连接吗?https://pypi.python.org/pypi/mock - 现在是python 3中stdlib的一部分。