ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

djangochannelsrestframework 之 GenericAsyncAPIConsumer:如何把 DRF 开发经验无缝迁移到 WebSocket

djangochannelsrestframework 之 GenericAsyncAPIConsumer:如何把 DRF 开发经验无缝迁移到 WebSocket djangochannelsrestframework 之 GenericAsyncAPIConsumer如何把 DRF 开发经验无缝迁移到 WebSocket【免费下载链接】djangochannelsrestframeworkA Rest-framework for websockets using Django channels-v4项目地址: https://gitcode.com/gh_mirrors/dj/djangochannelsrestframework如果你已经在用 Django REST FrameworkDRF写 REST API却开始被实时消息、双向通信的需求困扰那么djangochannelsrestframeworkDjango Channels REST Framework正是为你准备的桥梁。它基于 Django Channels 4 构建核心类GenericAsyncAPIConsumer几乎一比一复刻了 DRF 中GenericAPIView的开发体验同样的queryset、serializer_class、权限系统甚至连 CRUD 代码都可以直接搬运。本文将带你快速上手把积累的 DRF 开发经验无缝迁移到 WebSocket 世界。为什么说 WebSocket 需要一套DRF 式的开发范式传统 HTTP 请求是一问一答而 WebSocket 是一条全双工的长连接服务端可以主动推送、客户端可以随时发消息。但这也带来两个痛点——消息格式混乱各写各的 JSON 结构和权限/序列化逻辑重复。djangochannelsrestframework 的解法非常优雅把每一条 WebSocket 消息抽象成一个action动作复用 DRF 的序列化器与权限体系让实时接口的开发成本无限趋近于普通 REST API。GenericAsyncAPIConsumer 到底是什么打开项目的djangochannelsrestframework/generics.py你会发现它的类注释写着Base class for all other generic views也就是说它就是 DRFGenericAPIView的 WebSocket 版本。它继承自djangochannelsrestframework/consumers.py中的AsyncAPIConsumer并提供了这些与 DRF 完全同名的属性与方法DRF 中的写法GenericAsyncAPIConsumer 中的写法用途querysetqueryset数据查询集serializer_classserializer_class序列化器lookup_fieldlookup_field查找字段默认 pkget_queryset()get_queryset()获取查询集get_object()get_object()获取单个对象get_serializer()get_serializer()获取序列化器实例甚至 DRF 的经典提示语都原样保留如果你要覆盖视图方法请务必调用get_queryset()而不是直接访问queryset属性因为后者会被缓存。看到这些熟悉的代码你就明白什么叫无缝迁移了。一键安装与最小可用示例安装非常简单一条命令即可pip install djangochannelsrestframework接下来让我们用一段几乎和 DRF ViewSet 一模一样的代码写一个支持完整 CRUD 的用户接口。新建consumers.pyfrom django.contrib.auth.models import User from djangochannelsrestframework.generics import GenericAsyncAPIConsumer from djangochannelsrestframework.mixins import ( ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, PatchModelMixin, DeleteModelMixin, ) from .serializers import UserSerializer class UserConsumer( ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, PatchModelMixin, DeleteModelMixin, GenericAsyncAPIConsumer, ): queryset User.objects.all() serializer_class UserSerializer然后在routing.py中注册路由注意一定要使用.as_asgi()方法from django.urls import re_path from .consumers import UserConsumer websocket_urlpatterns [ re_path(r^ws/users/$, UserConsumer.as_asgi()), ]是的没有 viewset 注册、没有 router六个 Mixin 各提供一个 actionCRUD 接口就完成了。理解 WebSocket 消息协议action 与 request_id既然没有 URL 和 HTTP 方法客户端该怎么调用接口djangochannelsrestframework 规定了一套极简的消息协议每条请求只需两个核心字段{ action: list, request_id: 1723456789 }action要调用的动作名对应 consumer 上的方法request_id客户端自增的请求编号用于把异步返回与请求一一对应强烈建议携带。服务端统一返回如下结构的 JSON{ action: list, errors: [], response_status: 200, request_id: 1723456789, data: [{id: 1, username: test}] }前端 JavaScript 的使用方式也很直观const ws new WebSocket(ws://localhost:8000/ws/users/); ws.send(JSON.stringify({ action: create, request_id: Date.now(), data: {username: newuser, email: ab.com} }));六个 CRUD Mixin 一览能力全靠拼积木不需要像 ViewSet 那样必须全部实现你可以按需挑选 Mixin。它们的定义全部在djangochannelsrestframework/mixins.py中Mixin提供的 action返回状态码ListModelMixinlist列表200RetrieveModelMixinretrieve单条按 pk200CreateModelMixincreate创建201UpdateModelMixinupdate整体更新200PatchModelMixinpatch部分更新200DeleteModelMixindelete删除204只读接口只挂上ListModelMixin和RetrieveModelMixin就够了。数据量大还有PaginatedModelListMixin提供分页能力StreamedPaginatedListMixin甚至能把大数据集分页流式推送。这种自由组合的乐趣正是 DRF 开发者最熟悉的节奏。自定义 action扩展能力的关键一步内置 CRUD 不够用时用action()装饰器定义在djangochannelsrestframework/decorators.py随意扩展。它同时支持同步和异步方法同步方法会自动被包装进线程池执行避免阻塞事件循环from djangochannelsrestframework.decorators import action class UserConsumer(GenericAsyncAPIConsumer): action() async def get_stats(self, request_id, **kwargs): return {total_users: 42}, 200两个进阶参数值得收藏action(detachedTrue)仅用于异步方法让该动作脱离主循环独立运行。适合发邮件、请求外部 API这类耗时的操作运行期间连接仍可处理其他消息action(atomicTrue)仅用于同步方法强制把方法包进数据库事务默认跟随 Django 的ATOMIC_REQUESTS设置。权限系统DRF 权限直接复用这是无缝迁移含金量最高的部分。在consumers.py的AsyncAPIConsumer中权限机制完全复刻 DRF连接建立时检查can_connect每次 action 调用前检查has_permission不通过则返回权限异常。你只需把djangochannelsrestframework.permissions中的权限类放进permission_classesfrom djangochannelsrestframework import permissions class UserConsumer(GenericAsyncAPIConsumer): permission_classes (permissions.IsAuthenticated,)更棒的是框架内置了WrappedDRFPermission适配器见djangochannelsrestframework/permissions.py你从 DRF 里辛辛苦苦写的自定义权限类在这里几乎可以原样使用无需重写。进阶让前端实时订阅数据变化CRUD 只是基础WebSocket 的杀手锏是服务端主动推送。项目的djangochannelsrestframework/observer/模块提供了 observer 机制把某个 Django 信号如模型保存、自定义业务信号与 consumer 方法绑定当数据变化时自动向订阅的客户端推送。from djangochannelsrestframework.observer import ObserverModelInstanceMixin class UserConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset User.objects.all() serializer_class UserSerializer只需发送一条{action: subscribe_instance, pk: 42, request_id: 4}之后该用户的任何更新都会实时推送到这个连接——这正是做聊天、通知、协同编辑等实时功能的天然底座。最佳实践与避坑指南最后分享几条实战经验✅同步数据库操作在异步 action 中访问 ORM请用channels.db.database_sync_to_async包装或者干脆写成同步方法交给框架处理✅务必使用.as_asgi()在routing.py中千万不要实例化 consumerMyConsumer()必须用MyConsumer.as_asgi()这是官方文档反复强调的警告✅request_id 一定要传没有它前端将无法把异步响应与请求关联起来调试时寸步难行✅复用 DRF 序列化器queryset和serializer_class可以直接沿用 DRF 项目里的配置迁移成本趋近于零。想深入源码研究克隆项目后重点阅读djangochannelsrestframework/generics.pyGenericAsyncAPIConsumer 本体、mixins.py六大 CRUD Mixin和consumers.py消息分发与权限核心配合docs/目录下的官方教程很快就能吃透整个框架git clone https://gitcode.com/gh_mirrors/dj/djangochannelsrestframework从今天起别再为WebSocket 该怎么组织代码发愁了。带上你的 DRF 经验用 GenericAsyncAPIConsumer 半小时搭出第一个实时 API剩下的交给时间去打磨。【免费下载链接】djangochannelsrestframeworkA Rest-framework for websockets using Django channels-v4项目地址: https://gitcode.com/gh_mirrors/dj/djangochannelsrestframework创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表