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

如何在Django异步函数中正确使用transaction事务?

Django 3.1.7 异步函数中正确使用事务的方案

核心解决方案

由于Django 3.1.x的@transaction.atomic仅支持同步上下文,无法直接在异步函数中使用,正确做法是将需要事务包裹的逻辑写为同步函数,用sync_to_async包装后再在异步视图中调用。

代码示例

from django.db import transaction
from asgiref.sync import sync_to_async
from django.http import HttpResponse

# 1. 定义带事务的同步函数
@transaction.atomic
def test_sync():
    for _ in range(3):
        print("Test")
    # 此处可添加数据库操作,例如:
    # MyModel.objects.create(name="sample")

# 2. 将同步函数包装为异步可调用对象
test_async = sync_to_async(test_sync)

# 3. 异步视图中调用包装后的函数
async def call_test(request):
    await test_async()
    return HttpResponse("Call_test")

也可使用装饰器链式写法(注意顺序:@sync_to_async必须放在@transaction.atomic上方):

@sync_to_async
@transaction.atomic
def test_sync():
    for _ in range(3):
        print("Test")

async def call_test(request):
    await test_sync()
    return HttpResponse("Call_test")

错误原因分析

  1. 直接给异步函数加@transaction.atomic:
    @transaction.atomic内部依赖同步上下文专属API,在异步环境中调用会触发SynchronousOnlyOperation错误,这是Django对同步操作的安全限制。

  2. @sync_to_async放在@transaction.atomic下方(给异步函数加):
    装饰器执行顺序为从下往上,相当于先给异步函数套事务装饰器,再转成同步函数——事务逻辑已在异步上下文执行,依然触发同步操作限制。

  3. @sync_to_async放在@transaction.atomic上方(给异步函数加):
    相当于把异步函数转成同步可调用对象,但用await调用同步函数会误将其视为协程,导致"coroutine was never awaited"警告——同步函数无需await,且原函数为异步类型,转同步后调用方式完全错误。

额外说明

Django 4.0及以上版本提供了async transaction.atomic原生支持,但3.1.7属于旧版本,只能通过sync_to_async包裹同步事务函数的方式解决。

内容的提问来源于stack exchange,提问作者Super Kai - Kazuya Ito

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:05:20