我正在使用Django 1.8(使用pytest),以下是我的配置:
- 一个由
MasterSlaveRouter
管理的default
和readonly
数据库,该路由器根据操作是否为读取或写入操作将DB调用定向到其中一个连接。 - 在我的开发环境中,
settings.DATABASES
字典中的两个条目具有相同的设置(它们只是使用不同的连接,但数据库是相同的)。 - 然而,在我的测试环境中,只有一个名为
default
的数据库。 - 当保存
Foo
模型时,我会触发一个post_save
信号。 - 我有一个原子操作(由
@transaction.atomic
修饰),它修改了一个Foo
实例并在其上两次调用.save()
。由于没有传递自定义的using
参数给装饰器,因此该事务仅在default
数据库上处于活动状态。
post_save
回调将创建一个Bar
记录,该记录具有指向Foo
的OneToOneField
,但仅在检查该foo_id
的Bar
记录是否已存在后才这样做(以避免IntegrityError
)。此检查是通过执行以下查询来完成的:
already_exists = Bar.filter(foo=instance).exists()
第一次调用post_save
回调函数时,这是可以的。创建了一个Bar
记录,一切都很好。然而,在第二次调用中,尽管在之前的Foo
保存中刚刚创建了这样一个Bar
实例,但由于过滤是读取操作,所以使用readonly
连接执行,因此already_exists
最终包含值False
,并触发新记录的创建,最终抛出IntegrityError异常,因为当在default
连接上执行创建操作时,已经存在具有该foo_id
的记录。
我尝试将dev_settings
中的DATABASES
字典复制到test_settings
中,但这破坏了许多测试。然后我了解了override_settings
装饰器,并认为它非常适合我的情况。但令我惊讶的是,它不起作用。似乎在某个时候,当应用程序启动时,DATABASES
字典(仅带有default
的test_settings中的那个)被缓存,即使我更改了setting.DATABASES
,新值也不再被访问。
我该如何正确地为一个特定的测试覆盖数据库配置?
override_settings
的机制并不一定适用于某些类型的设置,特别是数据库设置。 - NeilG