You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:25:42