時(shí)聊天室的完整 7 步指南)
djangochannelsrestframework 入門教程從零搭建實(shí)時(shí)聊天室的完整 7 步指南【免費(fèi)下載鏈接】djangochannelsrestframeworkA Rest-framework for websockets using Django channels-v4項(xiàng)目地址: https://gitcode.com/gh_mirrors/dj/djangochannelsrestframeworkdjangochannelsrestframework簡(jiǎn)稱 DCRF是一個(gè)基于 Django Channels v4 構(gòu)建 WebSocket 實(shí)時(shí)接口的框架它提供了類似 Django REST FrameworkDRF的編程體驗(yàn)讓你能用熟悉的 Serializer、Mixin 和權(quán)限體系快速開發(fā)實(shí)時(shí)應(yīng)用。本文將通過搭建一個(gè)實(shí)時(shí)聊天室?guī)阃暾w驗(yàn)從安裝、建模到前后端聯(lián)調(diào)的 7 個(gè)核心步驟即使是剛接觸 WebSocket 的新手也能輕松跟上。為什么選擇 djangochannelsrestframework傳統(tǒng)的 Django 開發(fā)中HTTP 接口用 DRF 就能優(yōu)雅解決但一旦涉及實(shí)時(shí)推送聊天、通知、在線狀態(tài)就必須接觸 Channels 中略顯繁瑣的 Consumer 寫法。djangochannelsrestframework 的價(jià)值在于復(fù)用 DRF 技能Serializer、permission、Mixin 全部沿用你熟悉的 DRF 概念?異步原生基于 Channels v4天然支持高并發(fā) WebSocket 連接內(nèi)置觀察者模式model_observer可以讓你像訂閱信號(hào)一樣監(jiān)聽模型變化并實(shí)時(shí)推送開箱即用一行pip install即可獲得完整的 REST 風(fēng)格 WebSocket API第一步安裝 djangochannelsrestframework 與準(zhǔn)備工作在已經(jīng)完成 Django 與 Channels 基礎(chǔ)教程的前提下只需在同一個(gè) Python 環(huán)境中執(zhí)行pip install djangochannelsrestframework安裝后請(qǐng)確認(rèn)項(xiàng)目的settings.py中已正確配置ASGI_APPLICATION和channels應(yīng)用。這里有一個(gè)官方特別強(qiáng)調(diào)的坑在路由中聲明 Consumer 時(shí)必須使用.as_asgi()類方法例如RoomConsumer.as_asgi()千萬不要在代碼里實(shí)例化RoomConsumer()否則會(huì)引發(fā)嚴(yán)重問題。第二步創(chuàng)建聊天室的數(shù)據(jù)模型一個(gè)聊天室至少需要三個(gè)模型用戶、房間和消息。參考官方教程docs/tutorial/part_1.rst在chat/models.py中寫入from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): pass class Room(models.Model): name models.CharField(max_length255, nullFalse, blankFalse, uniqueTrue) host models.ForeignKey(User, on_deletemodels.CASCADE, related_namerooms) current_users models.ManyToManyField(User, related_namecurrent_rooms, blankTrue) class Message(models.Model): room models.ForeignKey(chat.Room, on_deletemodels.CASCADE, related_namemessages) text models.TextField(max_length500) user models.ForeignKey(User, on_deletemodels.CASCADE, related_namemessages) created_at models.DateTimeField(auto_now_addTrue)同時(shí)別忘了在settings.py中注冊(cè)自定義用戶模型AUTH_USER_MODEL chat.User然后執(zhí)行遷移命令同步數(shù)據(jù)庫。第三步編寫聊天數(shù)據(jù)的 DRF 序列化器DCRF 最大的爽點(diǎn)就在這里——你之前寫的 DRF Serializer 可以直接復(fù)用在chat/serializers.py中定義三個(gè)序列化器用于處理用戶、消息和房間數(shù)據(jù)的 JSON 轉(zhuǎn)換from rest_framework import serializers from .models import User, Room, Message class UserSerializer(serializers.ModelSerializer): class Meta: model User exclude [password] class MessageSerializer(serializers.ModelSerializer): created_at_formatted serializers.SerializerMethodField() user UserSerializer() class Meta: model Message exclude [] depth 1 def get_created_at_formatted(self, obj): return obj.created_at.strftime(%d-%m-%Y %H:%M:%S) class RoomSerializer(serializers.ModelSerializer): last_message serializers.SerializerMethodField() messages MessageSerializer(manyTrue, read_onlyTrue) class Meta: model Room fields [pk, name, host, messages, current_users, last_message] depth 1 read_only_fields [messages, last_message]第四步編寫核心 Consumer最關(guān)鍵的一步這是整個(gè) djangochannelsrestframework 教程的重頭戲。我們創(chuàng)建一個(gè)繼承ObserverModelInstanceMixin和GenericAsyncAPIConsumer的RoomConsumer核心類定義在源碼djangochannelsrestframework/generics.py中它負(fù)責(zé)處理 WebSocket 連接期間的各類 action。import json from channels.db import database_sync_to_async from djangochannelsrestframework.generics import GenericAsyncAPIConsumer from djangochannelsrestframework.observer import model_observer from djangochannelsrestframework.observer.generics import ObserverModelInstanceMixin, action from .models import Message, Room, User from .serializers import MessageSerializer, RoomSerializer, UserSerializer class RoomConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset Room.objects.all() serializer_class RoomSerializer lookup_field pk async def disconnect(self, code): if hasattr(self, room_subscribe): await self.remove_user_from_room(self.room_subscribe) await self.notify_users() await super().disconnect(code) action() async def join_room(self, pk, **kwargs): self.room_subscribe pk await self.add_user_to_room(pk) await self.notify_users() action() async def create_message(self, message, **kwargs): room await self.get_room(pkself.room_subscribe) await database_sync_to_async(Message.objects.create)( roomroom, userself.scope[user], textmessage )用 model_observer 實(shí)現(xiàn)消息實(shí)時(shí)推送model_observer是 DCRF 的殺手锏當(dāng)Message模型有新增時(shí)它會(huì)自動(dòng)把變更推送給所有訂閱者。配合groups_for_signal和serializer兩個(gè)裝飾方法就能實(shí)現(xiàn)按房間分組推送model_observer(Message) async def message_activity(self, message, observerNone, subscribing_request_ids[], **kwargs): for request_id in subscribing_request_ids: message_body dict(request_idrequest_id) message_body.update(message) await self.send_json(message_body) message_activity.groups_for_signal def message_activity(self, instance: Message, **kwargs): yield froom__{instance.room_id} yield fpk__{instance.pk} message_activity.groups_for_consumer def message_activity(self, roomNone, **kwargs): if room is not None: yield froom__{room} message_activity.serializer def message_activity(self, instance: Message, action, **kwargs): return dict(dataMessageSerializer(instance).data, actionaction.value, pkinstance.pk)注意一個(gè)小技巧凡是涉及數(shù)據(jù)庫同步操作的代碼都要用database_sync_to_async包裹避免阻塞事件循環(huán)。源碼中的相關(guān)輔助方法可參考djangochannelsrestframework/consumers.py和djangochannelsrestframework/observer/generics.py。第五步配置 WebSocket 路由在chat/routing.py中注冊(cè) WebSocket 路由讓 Channels 知道把ws/chat/room/的請(qǐng)求交給RoomConsumerfrom django.urls import re_path from . import consumers websocket_urlpatterns [ re_path(rws/chat/room/$, consumers.RoomConsumer.as_asgi()), ]然后在項(xiàng)目的asgi.py中用ProtocolTypeRouter把 HTTP 與 WebSocket 路由組合起來。至此后端已經(jīng)具備加入房間、發(fā)送消息、訂閱消息流和在線用戶實(shí)時(shí)更新的全部能力。第六步編寫頁面視圖與模板按官方教程docs/tutorial/part_2.rst的思路我們需要兩個(gè)頁面一個(gè)是輸入房間名并創(chuàng)建/加入房間的首頁index.html另一個(gè)是展示聊天記錄的聊天室頁面room.html。對(duì)應(yīng)的views.py非常簡(jiǎn)單from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render, reverse from .models import Room def index(request): if request.method POST: name request.POST.get(name, None) if name: room Room.objects.create(namename, hostrequest.user) HttpResponseRedirect(reverse(room, args[room.pk])) return render(request, chat/index.html) def room(request, pk): room get_object_or_404(Room, pkpk) return render(request, chat/room.html, {room: room})最后在chat/urls.py中注冊(cè)path(, views.index)和path(room/int:pk/, views.room)兩個(gè)路由。第七步前端 JavaScript 連接與聯(lián)調(diào)測(cè)試一切就緒后在room.html中加入 WebSocket 客戶端代碼。連接建立后依次發(fā)送join_room、retrieve、subscribe_to_messages_in_room等 action即可完成加入房間、拉取歷史消息和訂閱實(shí)時(shí)推送const room_pk {{ room.pk }}; const request_id {{ request.sessions.session_key }}; const chatSocket new WebSocket(ws://${window.location.host}/ws/chat/room/); chatSocket.onopen function(){ chatSocket.send(JSON.stringify({pk: room_pk, action: join_room, request_id: request_id})); chatSocket.send(JSON.stringify({pk: room_pk, action: retrieve, request_id: request_id})); chatSocket.send(JSON.stringify({pk: room_pk, action: subscribe_to_messages_in_room, request_id: request_id})); }; chatSocket.onmessage function(e) { const data JSON.parse(e.data); if (data.action create) { // 追加一條新消息到聊天窗口 console.log(新消息:, data.data); } };發(fā)送消息時(shí)只需一條指令chatSocket.send(JSON.stringify({ message: $(#chat-message-input).val(), action: create_message, request_id: request_id }));啟動(dòng)開發(fā)服務(wù)器打開兩個(gè)瀏覽器標(biāo)簽頁進(jìn)入同一個(gè)房間在其中一個(gè)發(fā)消息另一個(gè)頁面無需刷新即可實(shí)時(shí)收到進(jìn)階玩法不止于聊天室掌握這 7 步之后你已經(jīng)能駕馭 djangochannelsrestframework 的核心能力。DCRF 還提供了更多實(shí)用特性CRUD Mixin 全家桶ListModelMixin、CreateModelMixin、RetrieveModelMixin、UpdateModelMixin、PatchModelMixin、DeleteModelMixin定義在djangochannelsrestframework/mixins.py客戶端直接發(fā)送{action: list, request_id: 42}即可觸發(fā)對(duì)應(yīng)操作權(quán)限控制從djangochannelsrestframework.permissions導(dǎo)入IsAuthenticated、AllowAny用法與 DRF 完全一致訂閱自定義信號(hào)通過observer裝飾器訂閱 Django Signal實(shí)現(xiàn)任意業(yè)務(wù)事件的實(shí)時(shí)推送復(fù)用普通視圖view_as_consumer可以讓你把已有的 Django View 直接包裝成 WebSocket Consumer遷移成本幾乎為零如果你正在為項(xiàng)目引入實(shí)時(shí)通信能力djangochannelsrestframework 就是那個(gè)讓你少寫 80% 樣板代碼的寶藏框架。趕緊動(dòng)手把上面的聊天室跑起來吧【免費(fèi)下載鏈接】djangochannelsrestframeworkA Rest-framework for websockets using Django channels-v4項(xiàng)目地址: https://gitcode.com/gh_mirrors/dj/djangochannelsrestframework創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考