在使用 pytest-django 进行测试期间,Django 连接对象看不到第二个数据库的表
Django connections object does not see the tables of a second database during testing with pytest-django
底线: 在使用 pytest-django 进行测试期间,我的 Django 连接对象没有看到第二个数据库的 table 关系。
概览:
我有一个问题,我的 Django 连接对象似乎获得了错误的数据库信息。我在查询 'customers' 数据库中的 table 时偶然发现了这个问题,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' 上时,下面的两个游标都从 'default' 数据库中获取信息:
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的结果完全一样:只有'default'数据库中的table个名字。
这种情况发生在 pytest-django 和使用第二个 Postgres 数据库时,但只是有时。
在上面的查询中,我希望 df1 和 df2 不同,因为 'default' 和 'customers' 数据库不同。但是,有时,连接游标无法正确 'see' 第二个数据库中的所有信息。
奇怪的是,当我打印时连接设置显示不同:
print(connections.databases)
'connections' 对象包含两个不同的数据库,但一个是 "test" 数据库。 print 语句生成字典,但请注意 "test_customers":
(pdb) { 'default': { <conn info>}, 'test_customers': { <conn info> } }
似乎 Django 正在尝试建立一个测试数据库,但失败了,并且没有通过测试,因为 'test_customers' 中的 table 与生产中的不同。
我该如何解决这个问题,以便 pytest-django 在测试期间始终在第二个数据库(客户)中看到 tables?我在设置和拆卸数据库时做错了什么吗?
更新:阅读 pytest-django docs on DB creation/re-use 为我指明了正确的方向。但是,我对文档的这一部分有点不安:
Currently pytest-django does not specifically support Django’s
multi-database support. You can, however, use normal Django TestCase
instances to use its multi_db support.
If you have any ideas about the best API to support multiple databases
directly in pytest-django please get in touch, we are interested in
eventually supporting this but unsure about simply following Django’s
approach.
pytest-django
does not support multiple databases. When I was experimenting with multiple databases and parameters --reuse-db
/--create-db
结果是,有时它可以工作(所有数据库都已创建并且可以正确使用),有时它不工作(没有创建数据库或 Django抱怨数据库已经存在)。
恕我直言,有两种选择:1) 不要将 pytest 与 Django 一起使用; 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 = []
在 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
底线: 在使用 pytest-django 进行测试期间,我的 Django 连接对象没有看到第二个数据库的 table 关系。
概览: 我有一个问题,我的 Django 连接对象似乎获得了错误的数据库信息。我在查询 'customers' 数据库中的 table 时偶然发现了这个问题,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' 上时,下面的两个游标都从 'default' 数据库中获取信息:
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的结果完全一样:只有'default'数据库中的table个名字。
这种情况发生在 pytest-django 和使用第二个 Postgres 数据库时,但只是有时。
在上面的查询中,我希望 df1 和 df2 不同,因为 'default' 和 'customers' 数据库不同。但是,有时,连接游标无法正确 'see' 第二个数据库中的所有信息。
奇怪的是,当我打印时连接设置显示不同:
print(connections.databases)
'connections' 对象包含两个不同的数据库,但一个是 "test" 数据库。 print 语句生成字典,但请注意 "test_customers":
(pdb) { 'default': { <conn info>}, 'test_customers': { <conn info> } }
似乎 Django 正在尝试建立一个测试数据库,但失败了,并且没有通过测试,因为 'test_customers' 中的 table 与生产中的不同。
我该如何解决这个问题,以便 pytest-django 在测试期间始终在第二个数据库(客户)中看到 tables?我在设置和拆卸数据库时做错了什么吗?
更新:阅读 pytest-django docs on DB creation/re-use 为我指明了正确的方向。但是,我对文档的这一部分有点不安:
Currently pytest-django does not specifically support Django’s multi-database support. You can, however, use normal Django TestCase instances to use its multi_db support.
If you have any ideas about the best API to support multiple databases directly in pytest-django please get in touch, we are interested in eventually supporting this but unsure about simply following Django’s approach.
pytest-django
does not support multiple databases. When I was experimenting with multiple databases and parameters --reuse-db
/--create-db
结果是,有时它可以工作(所有数据库都已创建并且可以正确使用),有时它不工作(没有创建数据库或 Django抱怨数据库已经存在)。
恕我直言,有两种选择:1) 不要将 pytest 与 Django 一起使用; 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 = []
在 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