Django测试用例执行时未将数据保存至PostgreSQL问题求助
问题根源与解决方案
核心问题在于Django TestCase的事务隔离机制,和你设置的keepdb=True无关:
Django默认的TestCase类会为每个测试方法开启一个数据库事务,测试结束后自动回滚该事务——这是用来保证测试之间互相隔离的标准做法,所以不管测试成功或失败,事务回滚后所有测试期间创建的数据都会被清除,不会保留到数据库里。
你遇到的两个特殊现象的原因:
- 测试执行期间能查到数据:因为你是在同一个未提交的事务内查询,PostgreSQL允许事务内读取自己的未提交修改,所以能正常获取到数据。
- 数据库序列变化:PostgreSQL的自增序列操作是非事务性的,调用
nextval()生成新ID后,即使后续事务回滚,序列的值也不会回退,所以你会看到序列号涨了但对应的数据没保留。
解决方案
方案1:改用TransactionTestCase并禁用自动清理
把测试用例的基类从django.test.TestCase换成django.test.TransactionTestCase——这个类不依赖事务回滚来隔离测试,默认会在每个测试结束后截断所有表。如果你要保留数据,只需重写tearDown方法跳过清理:
from django.test import TransactionTestCase class MyTest(TransactionTestCase): def tearDown(self): # 注释掉父类的截断逻辑,不清理测试数据 # super().tearDown() pass
⚠️ 注意:这样会导致测试之间的数据互相污染,比如前一个测试创建的数据会影响后续测试。建议只在需要排查问题的特定测试中使用,或者在setUp方法里手动清理必要的数据来保证隔离性。
方案2:在TestCase中手动提交事务(仅用于临时排查)
如果不想切换基类,可以在测试方法内手动提交事务,让数据保留到数据库。但这会破坏测试隔离,只适合临时排查特定问题:
from django.test import TestCase from django.db import transaction class MyTest(TestCase): def test_debug_data(self): # 你的测试逻辑,创建测试数据 obj = MyModel.objects.create(name="debug_test") # 手动提交事务,让数据保留到数据库 transaction.commit()
方案3:自定义测试基类跳过事务回滚
创建一个自定义测试基类,跳过TestCase默认的事务回滚步骤:
from django.test import TestCase class KeepDataTestCase(TestCase): def _post_teardown(self): # 跳过父类的事务回滚逻辑 pass
⚠️ 注意:这个方法依赖Django的内部实现,不同版本可能有变动,使用前请测试兼容性。
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

