当前位置:首页 > 文章列表 > 文章 > python教程 > Python Django 实战:async view 里别直接摸同步 ORM

Python Django 实战:async view 里别直接摸同步 ORM

来源:Python 博主原创 2026-06-04 13:48:48 0浏览 收藏

Django 现在支持异步视图,很多 Python 后端团队一升级到 ASGI,就想把接口全改成 async def。我支持这个方向,但不支持一把梭。最常见的事故是:异步视图里直接调用同步 ORM,开发环境偶尔报 SynchronousOnlyOperation,线上则表现成 P99 飙升、连接池吃紧、事件循环被拖住。

这篇文章不讲 Django 入门,也不搬官方 API 列表。我用一个订单详情页的排障过程说明:什么时候 async view 真有收益,ORM 怎么隔离,sync_to_async 怎么用,事务边界怎么收口,以及上线前我会检查哪些指标。

Python Django 异步视图治理思维导图
治理思路:ASGI 能提升并发等待能力,但 ORM、事务和同步中间件边界必须单独设计。

业务场景:异步详情页越改越慢

假设订单详情页需要同时取订单、调用会员服务、调用风控服务。团队把视图改成异步以后,外部 HTTP 调用确实可以并发等待,但代码里还保留了同步 ORM。

# views.py
async def order_detail(request, order_id: int):
    order = Order.objects.select_related("user").get(pk=order_id)
    risk = await risk_client.get_score(order.user_id)
    member = await member_client.get_profile(order.user_id)
    return JsonResponse({"order": order.no, "risk": risk, "member": member})

这段代码的问题不是“语法不 async”,而是边界混乱:异步视图运行在事件循环里,同步 ORM 访问会碰到 Django 的异步安全保护;即便绕过去,也可能把线程切换、连接复用和事务行为搞得很难预测。

先判断 async view 是否值得

我不会为了“看起来现代”改 async。Django async view 适合 I/O 等待多、可并发发起外部调用的接口,比如聚合多个 HTTP 服务、WebSocket、长轮询、轻量异步缓存访问。如果接口主要是 ORM 查询和模板渲染,同步视图反而更简单稳定。

Python Django ASGI 异步请求链路
请求链路:async view 可以承载非阻塞 I/O,但 ORM 和事务要经过清晰的同步边界。

上线前我会把接口分成三类:纯同步 ORM 密集型继续同步;外部 I/O 密集型考虑 async;混合型则把同步 ORM 封装到边界函数里,不让业务代码到处直接调用。

方案一:能用异步 ORM 就直接 await

Django 已经提供了一批异步 QuerySet 方法,比如 agetacreateaupdate 等。简单查询可以直接用异步 ORM 表达,代码边界最干净。

async def order_detail(request, order_id: int):
    order = await Order.objects.select_related("user").aget(pk=order_id)
    risk, member = await asyncio.gather(
        risk_client.get_score(order.user_id),
        member_client.get_profile(order.user_id),
    )
    return JsonResponse({"order": order.no, "risk": risk, "member": member})

这里的收益来自两个地方:ORM 调用遵守异步边界,两个外部服务可以并发等待。注意,asyncio.gather 不是越多越好,下游服务和连接池都有容量,生产里仍然要配超时、限流和熔断策略。

方案二:复杂 ORM 放进同步函数,再用 sync_to_async 包起来

现实项目里,很多查询不是一行 aget 能解决。比如带事务、复杂预取、历史库兼容、老代码复用。这个时候我更愿意把 ORM 逻辑封装成同步函数,再在 async view 里用 sync_to_async 调用。

from asgiref.sync import sync_to_async

def load_order_snapshot(order_id: int) -> dict:
    order = (
        Order.objects
        .select_related("user")
        .prefetch_related("items")
        .get(pk=order_id)
    )
    return {"no": order.no, "user_id": order.user_id, "item_count": len(order.items.all())}

async def order_detail(request, order_id: int):
    snapshot = await sync_to_async(load_order_snapshot, thread_sensitive=True)(order_id)
    risk = await risk_client.get_score(snapshot["user_id"])
    return JsonResponse({"order": snapshot, "risk": risk})

我喜欢这种写法,因为它把“同步世界”和“异步世界”分得很清楚。视图负责异步编排,函数负责 ORM 读取。出了问题也容易定位:到底是数据库慢,还是外部服务慢。

Python Django async view ORM 边界代码对照
代码审查重点:异步视图直接调用同步 ORM 是红线;复杂 ORM 应封装到同步边界里。

事务别跨过 await

我见过最危险的写法,是在事务里混入外部异步调用。事务打开后等待下游 HTTP,数据库连接被占住,锁时间变长,一旦下游抖动,数据库也跟着遭殃。

# 不推荐:事务边界里等待外部服务
async def pay_callback(request):
    with transaction.atomic():
        order = Order.objects.get(no=request.POST["order_no"])
        result = await payment_client.confirm(order.no)
        order.status = result.status
        order.save()

更稳的做法是把事务内的数据库更新封装到同步函数,外部调用放在事务外。需要强一致时,用状态机、幂等键和补偿任务来兜底,不要用一个跨网络的长事务硬扛。

def mark_paid(order_no: str, status: str) -> None:
    with transaction.atomic():
        order = Order.objects.select_for_update().get(no=order_no)
        order.status = status
        order.save(update_fields=["status"])

async def pay_callback(request):
    result = await payment_client.confirm(request.POST["order_no"])
    await sync_to_async(mark_paid, thread_sensitive=True)(request.POST["order_no"], result.status)
    return JsonResponse({"ok": True})

诊断步骤:先找同步边界泄漏

Django async 改造出问题时,我通常这样查:

  • 检查 async view 里是否直接出现 Model.objects.getfiltersavetransaction.atomic
  • 检查同步中间件是否让请求在 sync/async 之间频繁切换。
  • 按接口记录 P95/P99、数据库查询耗时、外部服务耗时和线程池排队时间。
  • 压测混合流量:一个慢外部服务是否拖慢纯数据库接口。
  • 确认数据库连接数、事务持续时间和慢查询是否同步上升。

上线检查清单

  • 只有 I/O 等待明显的接口才改 async view,ORM 密集型接口保持同步也可以。
  • async view 中禁止直接调用同步 ORM,简单查询优先用异步 ORM 方法。
  • 复杂 ORM 和事务逻辑封装成同步函数,用 sync_to_async(..., thread_sensitive=True) 调用。
  • 事务边界内不等待外部 HTTP,不把数据库锁交给下游服务质量决定。
  • 同步中间件逐个盘点,避免 ASGI 下频繁上下文切换。
  • 压测观察 P99、线程池等待、数据库连接数、事务时长、异常日志。
  • 保留回滚到同步视图或 WSGI 路径的方案,先灰度非核心接口。

总结

Django 的 async 支持不是“把 def 改成 async def”这么简单。它真正考验的是边界感:哪里可以异步等待,哪里必须同步收口,哪里要用线程敏感模式保护 ORM,哪里不能让事务跨过网络调用。

我的经验是,Django async 改造要小步走。先挑外部 I/O 明显的接口,画清 ORM 边界,压测指标看懂以后再扩大范围。这样 async view 才是生产优化,而不是给老系统添一层新的不确定性。

版本声明
本文转载于:Python 博主原创 如有侵犯,请联系study_golang@163.com删除
Python FastAPI 实战:别把耗时任务塞进请求生命周期Python FastAPI 实战:别把耗时任务塞进请求生命周期
上一篇
Python FastAPI 实战:别把耗时任务塞进请求生命周期
Maven 依赖冲突排查:NoSuchMethodError 不是玄学,先看依赖树
下一篇
Maven 依赖冲突排查:NoSuchMethodError 不是玄学,先看依赖树
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ChatExcel酷表:告别Excel难题,北大团队AI助手助您轻松处理数据
    ChatExcel酷表
    ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
    5963次使用
  • Any绘本:开源免费AI绘本创作工具深度解析
    Any绘本
    探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
    6383次使用
  • 可赞AI:AI驱动办公可视化智能工具,一键高效生成文档图表脑图
    可赞AI
    可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
    6193次使用
  • 星月写作:AI网文创作神器,助力爆款小说速成
    星月写作
    星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
    8167次使用
  • MagicLight.ai:叙事驱动AI动画视频创作平台 | 高效生成专业级故事动画
    MagicLight
    MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
    6773次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码