Django在运行测试时会忽略路由器吗? [英] Django ignores router when running tests?

查看:75
本文介绍了Django在运行测试时会忽略路由器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


  1. 要连接到应用程序要生成的实际数据,
  2. >
  3. 对于参考主数据系统,它完全不受我的控制

我的问题是我所拥有的是,我的Web应用程序绝对不能触摸第二个数据库中的数据。我通过使用2个(子)应用程序解决了大多数问题,每个数据库连接一个。我创建了一个路由器文件来路由任何迁移,并写入第一个应用程序



我还使用

使第二个应用程序中的所有模型都处于非托管状态

  model.meta.managed = False 

选项。



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



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



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



如何运行测试,不要尝试创建第二个数据库

谢谢!



编辑:代码



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



<$ django.db导入模型中的p $ p>


类MdmMeta(对象):
db_tablespace ='MDM_ADM'
managed = False
ordering = ['name']


类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')
实体名称=模型.CharField(max_length = 255,db_column ='ENTITYNAME')

entry_guid = models.PositiveIntegerField(primary_key = True,db_column ='ENTRYGUID')

名称= models.CharField(max_length = 255,db_column ='NAME')
描述= 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):
引发异常('不保存MDM模型!')

def delete(自身,* args,** kwargs):
引发异常('不删除MDM模型!')

def __str __(self):
return self.name

class Meta(MdmMeta):
abstract = True


#在此处创建模型。
类MdmSpecies(MdmType):
类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 ='品种'
verbose_name_plural ='品种的

...

路由器:

  __ author__ ='CoesseWa'

class MdmRouter(object):

def db_for_read(self,model,** hints):
if model._meta.app_label =='mdm':
#返回'默认'
返回'mdm_db'#尝试执行使用一个数据库连接
返回'默认'

def db_for_write(自身,模型,**提示):
返回'默认'

def allow_relation (self,obj1,obj2,** hints):
返回None

def allow_migrate(self,db,m odel):
如果model._meta.app_label =='mdm':
返回False

设置:

  DATABASES = {
'默认':{
'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'),
},
}

一个测试用例:

 来自django.test.testcases import TestCase 

__author__ ='CoesseWa'


类ModelTest(TestCase):

def test_getting_guid_for_mdm_field(self):
self.assertIsNotNone(1)

运行此测试时的输出:

  ... 
正在销毁旧的测试用户...

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

 创建测试用户... 

=>接下来的几行应该永远不会发生。失败,因为我使用了只读用户(幸运的是)

 为别名'mdm_db'创建测试数据库... 

失败(ORA-01031:特权不足
创建测试数据库时出错:ORA-01031:特权不足


解决方案

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

 数据库= {
'默认':{
'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'),
}, $ b'mdm_db':{
'ENGINE':'django.d b.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',#添加了此设置
}
},
}

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


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



在配置测试环境后,测试版本复制
不会被创建。取而代之的是与副本的连接将
重定向到默认位置。


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



感谢所有输入!


I have a django application that uses 2 database connections:

  1. To connect to the actual data the app is to produce
  2. To a reference master data system, that is maintained completely outside my control

The issue that I'm having, is that my webapp can absolutely NOT touch the data in the 2nd database. I solved most of the issues by using 2 (sub)apps, one for every database connection. I created a router file that router any migration, and writing to the first app

I also made all the models in the 2nd app non managed, using the

model.meta.managed = False

option.

To be sure, the user I connect to the 2nd database has read only access

This works fine for migrations and running. However, when I try to run tests using django testcase, Django tries to delete and create a test_ database on the 2nd database connection.

How can I make sure that Django will NEVER update/delete/insert/drop/truncate over the 2nd connection

How can I run tests, that do not try to create the second database, but do create the first.

Thanks!

edited: code

model (for the 2nd app, that should not be managed):

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'

...

router:

__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

settings:

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'),
    },
}

one testcase:

from django.test.testcases import TestCase

__author__ = 'CoesseWa'


class ModelTest(TestCase):

    def test_getting_guid_for_mdm_field(self):
        self.assertIsNotNone(1)

output from when running this tests:

... 
Destroying old test user...

(before this point, django creates the test database for my first connection = OK)

Creating test user...

=> This next lines should never happen. Fails because I use a read only user (luckily)

Creating test database for alias 'mdm_db'...

Failed (ORA-01031: insufficient privileges 
Got an error creating the test database: ORA-01031: insufficient privileges

解决方案

I solved this by changing the DATABASES.TEST definition. I added the TEST['MIRROR'] = 'default' to the mdm_db database entry.

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
        }
    },
}

According to the documentation this option can be abused to skip database creation:

However, the replica database has been configured as a test mirror (using the MIRROR test setting), indicating that under testing, replica should be treated as a mirror of default.

When the test environment is configured, a test version of replica will not be created. Instead the connection to replica will be redirected to point at default.

Running my tests now skips creation of the second database.

Thanks for all the input!!

这篇关于Django在运行测试时会忽略路由器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆