Django WebSocket AsyncConsumer [0]


少し前にコーカサス(Korea Hack 2021)に参加したことがあります.30時間も開発に努力したが、コードはかなり悪い.
すべての惨事の元凶はWebSocketだ.
djangoでは、WebSocket通信を実現するために、本当に多くの挿入作業を行いました.次回は同じシャベルを作らないように整理しておきたいと思います.

setting.py


チャネルモジュールを用いてソケット通信を行う.djangoに関連付けるには、チャネルレイヤを設定します.pyに明記する必要があります.
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer"
    }
}

routing.py


ではDjangoは自分で見て選びましょう見つけました.ここで,HTTPとWebSocketは別々にルーティングされる.
from django.urls import path

from channels.routing import URLRouter, ProtocolTypeRouter
from channels.auth import AuthMiddlewareStack

from main.consumers import WriteConsumer
from main.consumers import AuthConsumer

application = ProtocolTypeRouter({
    'websocket': AuthMiddlewareStack(
        URLRouter([
            path("write/<str:board_url>/<str:session_id>/", WriteConsumer.as_asgi()),
            path("auth/<str:board_url>/<str:session_id>/", AuthConsumer.as_asgi()),
        ])
    )
})
このようにルートを設定するのは慣れていると思いませんか?
urlpatterns = [
    path('new_board', views.make_board),
    path('<uuid:board_url>', views.get_board),
]
urls.pyとよく似ています.routing.pyの利用者はhttpを処理する際のビューと似ていると考えられる.
次は消費者ですpyを記入する必要があります.これは一番難しいことで、長い時間がかかります.

consumers.py


AsyncConsumer(災害の始まり)を使用しました.クラス名からjavascriptのようにasyncとして動作することがわかります.pythonではasync符号化はどうしても本当に適応できません.基本的に動作の仕方はこうです.
class EchoConsumer(AsyncConsumer):

    async def websocket_connect(self, event):
        await self.send({
            "type": "websocket.accept",
        })

    async def websocket_receive(self, event):
        await self.send({
            "type": "websocket.send",
            "text": event["text"],
        })

websocket_connect


WebSocket接続要求がクライアントから受信されると、websocket_connect関数が呼び出されます.send()は、前述のようにクライアントに応答を送信し、"type": "websocket.accept"を送信することによってWebSocket接続が正常であることを通知する.

websocket_receive


その後、クライアントからWebSocketパケットに到達すると、websocket_receive関数が機能します.クライアントはjson形式でデータを送信することができ、サーバはwebsocket_receive関数のパラメータeventとしてデータを受信することができる.

  • クライアント:{"text": "hello"}サーバ:text = event["text"] #text == "hello"
  • 上にはsend({"type": "websocket.send", "text": event["text"]})の線があります.最初は理解しにくいのですが、あなたのおかげで本当にシャベルの仕事をたくさんしました.これはよく見る必要があります.

    send type

    send()の論点のtypeはCallbackと考えられる.asyncのコールバックはJavaScriptかPythonか...どうせそうだ.残りはそのコールバック関数に入るパラメータと見なすことができる.すなわち、send({"type": "websocket.send", "text": event["text"]})は、websocket.send(text=event["text"])を超えるコールバックと見なすことができる.
    つまり、先ほどsend()でクライアントに応答を送ると言っていましたが、そうではない可能性もあります.正確には、send()からwebsocket.send(text=event["text"])にダイヤルバックし、ここでクライアントに返信する.なお、その回答内容はtextであった.
    コーカサス大会当日、彼はこのような動作方式を完全に理解せず、"text"の異なる動作を変えたが、なぜ応答を得られなかったのか、長い間悩んでいた.
    たとえば,send({"type": "websocket.send", "pos": 1})ではcallbackからwebsocket.send(pos=1),websocket.send함수からtextへの論点がないため,何の応答もない.
    それさえ理解すれば、djangoでWebSocketを実現するのはずっと簡単です.