模型實(shí)例變化的完整教程)
djangochannelsrestframework ObserverModelInstanceMixin訂閱單個(gè)模型實(shí)例變化的完整教程【免費(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 REST 框架它把 Django REST Framework 熟悉的開發(fā)體驗(yàn)帶到了實(shí)時(shí)通信場(chǎng)景中。本教程將聚焦其中的ObserverModelInstanceMixin——一個(gè)專門用于訂閱單個(gè)模型實(shí)例變化的混入類幫你用最少的代碼實(shí)現(xiàn)某一條數(shù)據(jù)被修改或刪除時(shí)前端實(shí)時(shí)收到通知的核心功能全程附完整代碼示例。為什么需要訂閱單個(gè)模型實(shí)例變化在很多實(shí)時(shí)應(yīng)用里我們并不需要監(jiān)聽整張表而只關(guān)心某一條記錄的變化比如在線協(xié)作編輯時(shí)其他用戶對(duì)當(dāng)前文檔的修改要即時(shí)同步后臺(tái)修改了某個(gè)商品價(jià)格正在查看該商品頁面的用戶要立刻刷新訂單狀態(tài)流轉(zhuǎn)后下單用戶端要實(shí)時(shí)收到狀態(tài)更新。傳統(tǒng)的輪詢方案浪費(fèi)資源且延遲高而 DCRF 的ObserverModelInstanceMixin讓你只用幾行代碼就能把任意一條 Django 模型實(shí)例的 create / update / delete 事件通過 WebSocket 實(shí)時(shí)推送給訂閱者。核心原理一個(gè)實(shí)例對(duì)應(yīng)一個(gè)頻道組理解ObserverModelInstanceMixin之前先要知道它的底層機(jī)制。它定義在 generics.py 中由ObserverConsumerMixin和RetrieveModelMixin組合而成核心是一個(gè)名為handle_instance_change的模型觀察者M(jìn)odelObserverModelObserver通過 Django 的post_init、post_save、post_delete信號(hào)監(jiān)聽模型變化相關(guān)邏輯在 model_observer.py默認(rèn)的分組規(guī)則是模型名 主鍵見 generics.py也就是說每個(gè)實(shí)例擁有獨(dú)立的頻道組只有訂閱了該實(shí)例的連接才會(huì)收到它的變更消息消息發(fā)送被安排在數(shù)據(jù)庫事務(wù)提交之后on_commit避免回滾的數(shù)據(jù)被誤推送。這套機(jī)制的好處很明顯客戶端之間互不干擾多個(gè)用戶訂閱同一條數(shù)據(jù)時(shí)一次事件只序列化一次、按組廣播性能開銷極小。三步快速接入創(chuàng)建實(shí)時(shí)訂閱 Consumer下面以 Django 內(nèi)置的User模型為例完整走一遍接入流程。第一步準(zhǔn)備序列化器# serializers.py from rest_framework import serializers from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer): class Meta: model User fields [id, username, email, password] extra_kwargs {password: {write_only: True}}第二步編寫 Consumer只需要繼承ObserverModelInstanceMixin和GenericAsyncAPIConsumer再聲明queryset與serializer_class即可# consumers.py from django.contrib.auth.models import User from djangochannelsrestframework.generics import GenericAsyncAPIConsumer from djangochannelsrestframework.observer.generics import ObserverModelInstanceMixin from .serializers import UserSerializer class UserConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset User.objects.all() serializer_class UserSerializer完成這兩步后你的 Consumer 就自動(dòng)擁有了三個(gè)動(dòng)作retrieve查詢單條、subscribe_instance訂閱實(shí)例變化、unsubscribe_instance取消訂閱。第三步配置路由# routing.py from django.urls import re_path from . import consumers websocket_urlpatterns [ re_path(r^ws/$, consumers.UserConsumer.as_asgi()), ]完整示例可參考官方文檔 observer_model_instance.rst。前端訂閱流程從連接 WebSocket 到收到實(shí)時(shí)通知1. 建立 WebSocket 連接const ws new WebSocket(ws://localhost:8000/ws/); ws.onmessage function (e) { console.log(JSON.parse(e.data)); };2. 訂閱某個(gè)實(shí)例發(fā)送subscribe_instance動(dòng)作pk指定要監(jiān)聽的數(shù)據(jù)request_id是本次訂閱的標(biāo)識(shí)后續(xù)所有變更通知都會(huì)帶上它ws.send(JSON.stringify({ action: subscribe_instance, request_id: 1550050, pk: 1, }));成功后服務(wù)端返回 201 狀態(tài)碼{ action: subscribe_instance, errors: [], response_status: 201, request_id: 1550050, data: null }3. 觸發(fā)一次更新觀察實(shí)時(shí)推送在 Django shell 中修改這條數(shù)據(jù) from django.contrib.auth.models import User user User.objects.get(pk1) user.username edited user name user.save()前端立刻就會(huì)收到update通知data中已經(jīng)是序列化后的最新數(shù)據(jù){ action: update, errors: [], response_status: 200, request_id: 1550050, data: {email: 1example.com, id: 1, username: edited user name} }如果該實(shí)例被刪除則會(huì)收到delete通知狀態(tài)碼 204。整個(gè)訂閱—推送—取消訂閱的完整調(diào)用鏈路都可以在官方測(cè)試 test_model_observer.py 中看到詳細(xì)的斷言示例。高級(jí)技巧權(quán)限控制與多實(shí)例訂閱在推送前校驗(yàn)權(quán)限ObserverModelInstanceMixin的handle_observed_action見 generics.py在每次收到變更事件時(shí)都會(huì)先執(zhí)行check_permissions因此你只要在 Consumer 中聲明permission_classes就可以對(duì)訂閱者做實(shí)時(shí)校驗(yàn)權(quán)限不足的消息會(huì)被攔截并走h(yuǎn)andle_exception處理。同一條連接訂閱多個(gè)實(shí)例你可以在同一個(gè) WebSocket 連接上用不同的request_id訂閱多條數(shù)據(jù)例如同時(shí)訂閱 id1 和 id2 的用戶。服務(wù)端會(huì)分別維護(hù)各自的頻道組映射更新時(shí)只向?qū)?yīng)實(shí)例的訂閱者推送互不串?dāng)_可參考測(cè)試 test_model_observer.py。事務(wù)內(nèi)多次修改只推送一次如果在一個(gè)事務(wù)里對(duì)同一實(shí)例連續(xù)保存多次DCRF 會(huì)借助pending_messages機(jī)制合并消息只推送最后一次的結(jié)果見 model_observer.py既避免了重復(fù)推送也保證客戶端拿到的一定是最終狀態(tài)。常見問題排查收不到通知先確認(rèn)是否真的調(diào)用了subscribe_instance且pk存在再檢查數(shù)據(jù)庫寫入與 WebSocket 是否處于同一個(gè) Django 進(jìn)程中channel layer 需正確配置。數(shù)據(jù)庫回滾了但前端收到消息正常不會(huì)發(fā)生因?yàn)?DCRF 使用transaction.on_commit在事務(wù)提交后才真正發(fā)送消息。想監(jiān)聽整張表的變更可以改用model_observer裝飾器配合groups_for_signal自定義分組詳見 observer.py??偨Y(jié)ObserverModelInstanceMixin是 djangochannelsrestframework 中性價(jià)比極高的實(shí)時(shí)能力入口一個(gè) mixin、三個(gè)動(dòng)作、幾十行代碼就能為你的 Django 應(yīng)用補(bǔ)上單條數(shù)據(jù)實(shí)時(shí)推送的能力。無論是訂單狀態(tài)、在線協(xié)作還是消息提醒掌握它都能讓 WebSocket 開發(fā)事半功倍。建議直接閱讀官方示例 observer_model_instance.rst 和源碼 generics.py結(jié)合本教程動(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),僅供參考