9

底线:在使用 pytest-django 进行测试期间,我的 Django 连接对象没有看到第二个数据库的表关系。

概述: 我有一个问题,我的 Django 连接对象似乎获取了错误的数据库信息。当我在“客户”数据库中查询表时,我偶然发现了这个问题,Django 告诉我关系不存在。使用 settings.py 数据库部分设置如下:

DATABASES = {
    'default': {
        'NAME': 'user_data',
        'ENGINE': 'django.db.backends.postgres',
        'USER': 'postgres_1',
        'PASSWORD': 'superS3cret'
    },
    'customers': {
        'NAME': 'customer_data',
        'ENGINE': 'django.db.backends.postgres',
        'USER': 'postgres_1',
        'PASSWORD': 'superS3cret'
    }
}

当我在目录上运行“pytest”时,下面的两个光标都从“默认”数据库中获取信息:

sql = """SELECT table_name FROM information_schema.tables WHERE table_nameschema='public'"""

default = connections["default"].cursor()
default.execute(sql)
raw_data = default.fetchall()
sql_columns = [col[0] for col in default.description]
df1 = pd.DataFrame(raw_data, columns=sql_columns)

customers = connections["customers"].cursor()
customers.execute(sql)
raw_data = customers.fetchall()
sql_columns = [col[0] for col in customers.description]
df2 = pd.DataFrame(raw_data, columns=sql_columns)

df1 和 df2 的结果完全相同:只有“默认”数据库中的表名。

pytest-django 和使用第二个 Postgres 数据库时会发生这种情况,但有时只有.

在上面的查询中,我希望 df1 和 df2 是不同的,只要“默认”和“客户”数据库不同。但是,有时,连接游标无法正确“看到”第二个数据库中的所有信息。

奇怪的是,当我打印时,连接设置显示不同:

print(connections.databases)

“连接”对象包含两个不同的数据库,但一个是“测试”数据库。print 语句产生一个字典,但请注意“ test_customers ”:

(pdb) { 'default': { <conn info>}, 'test_customers': { <conn info> } }

似乎 Django 正在尝试建立一个测试数据库,但失败了,并且没有通过测试,因为“test_customers”中的表与生产中的表不同。

如何解决此问题,以便 pytest-django 在测试期间始终看到第二个数据库(客户)中的表?我在设置和拆卸数据库时做错了吗?

更新:阅读有关数据库创建/重用的 pytest-django 文档为我指明了正确的方向。但是,我对文档的这一部分感到有些不安:

目前 pytest-django 并没有专门支持 Django 的多数据库支持。但是,您可以使用普通的 Django TestCase 实例来使用它的 multi_db 支持。

如果您对直接在 pytest-django 中支持多个数据库的最佳 API 有任何想法,请与我们联系,我们有兴趣最终支持这一点,但不确定是否仅仅遵循 Django 的方法。

4

2 回答 2

3

pytest-django 不支持多数据库。当我尝试使用多个数据库和参数--reuse-db/--create-db结果是,有时它可以工作(所有数据库都已创建并且可以正确使用),有时它不起作用(数据库没有创建或 Django 抱怨数据库已经存在)。

恕我直言,有两种选择:1)不要在 Django 中使用 pytest;2)简化您的测试,因此您不需要多个数据库。对于选项 2) 我正在使用此设置:

正常settings

DATABASES = {
    'default': ...,
    'secondary': ...,
}

pytest.ini

[pytest]
...
DJANGO_SETTINGS_MODULE=my_app.settings.test
...

test.py

# Import all from normal settings
from .base import *

DATABASES.pop('secondary')
# This will route all queries and migrations to the default DB
DATABASE_ROUTERS = []
于 2018-05-03T10:36:03.290 回答
0

在 test_settings.py -> 猴子补丁

from django.db.models.query import QuerySet, RawQuerySet
queryset_using = QuerySet.using
raw_queryset_using = RawQuerySet.using


def new_queryset_using(self, alias):
    return queryset_using(self, 'default')


def new_raw_queryset_using(self, alias):
    return raw_queryset_using(self, 'default')


QuerySet.using = new_queryset_using
RawQuerySet.using = new_raw_queryset_using
于 2019-07-16T18:02:25.690 回答