Django channels hướng dẫn cơ bản

Giới thiệu Channels kết hợp hỗ trợ chế độ xem không đồng bộ gốc của Django, cho phép các dự án của Django xử lý không chỉ HTTP mà còn các giao thức yêu cầu kết nối lâu dài – WebSockets, MQTT, chatbots, đài nghiệp dư, v.v. Nó thực hitện điều này rong khi vẫn

Giới thiệu

Channels kết hợp hỗ trợ chế độ xem không đồng bộ gốc của Django, cho phép các dự án của Django xử lý không chỉ HTTP mà còn các giao thức yêu cầu kết nối lâu dài – WebSockets, MQTT, chatbots, đài nghiệp dư, v.v.

Nó thực hitện điều này rong khi vẫn bảo toàn tính chất đồng bộ và dễ sử dụng của Django, cho phép bạn chọn cách bạn viết mã của mình – đồng bộ theo phong cách như chế độ xem Django, hoàn toàn không đồng bộ hoặc kết hợp cả hai. Trên hết, nó cung cấp tích hợp với hệ thống xác thực của Django, hệ thống phiên và hơn thế nữa, giúp việc mở rộng dự án chỉ HTTP của bạn sang các giao thức khác dễ dàng hơn bao giờ hết.

Channels cũng kết hợp kiến ​​trúc hướng sự kiện này với các lớp kênh , một hệ thống cho phép bạn dễ dàng giao tiếp giữa các quy trình và tách dự án của bạn thành các quy trình khác nhau.

Cài đặt

start app

django-admin startproject myapp
python3 manage.py startapp chat

Sau đó create urls.py trong app chat. thêm thư mục templates và tạo file chat.html trong templates

myapp
├─ myapp
│  ├─ __init__.py
│  ├─ asgi.py
│  ├─ settings.py
│  ├─ urls.py
│  └─ wsgi.py
├─ chat
│  ├─ __init__.py
│  ├─ admin.py
│  ├─ apps.py
│  ├─ models.py
│  ├─ tests.py
│  ├─ urls.py
│  └─ views.py
├─ templates
│  └─ chat.html
└─ manage.py

Tiếp đết chúng ta thêm app chat vào setting.py

# mysite/settings.py
INSTALLED_APPS =['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','chat',]

Sửa file chat.html

<!DOCTYPEhtml><html><head><metacharset="utf-8"/><title>Chat Rooms</title></head><body>
    What chat room would you like to enter?<br><inputid="room-name-input"type="text"size="100"><br><inputid="room-name-submit"type="button"value="Enter"><script>
        document.querySelector('#room-name-input').focus();
        document.querySelector('#room-name-input').onkeyup=function(e){if(e.keyCode ===13){// enter, return
                document.querySelector('#room-name-submit').click();}};

        document.querySelector('#room-name-submit').onclick=function(e){var roomName = document.querySelector('#room-name-input').value;
            window.location.pathname ='/chat/'+ roomName +'/';};</script></body></html>

chỉnh sửa file urls.py trong app chat

# chat/urls.pyfrom django.urls import path
from.import views
urlpatterns =[
    path('chat/',  views.chat),
    path('chat/<str:room_name>/', views.chat_room),]

chỉnh sửa views.py trong app chat

def chat(request):returnrender(request,'chat.html')

def chat_room(request, room_name):returnrender(request,'room.html',{"room_name": room_name})

Chỉnh sửa file urls.py trong myapp

# myapp/urls.pyfrom django.conf.urls import include
from django.urls import path
from django.contrib import admin

urlpatterns =[
    path('admin/', admin.site.urls),
    path('', include('chat.urls')),]

channels

pip install channels

Tiếp tục chỉnh sửa file setting.py

INSTALLED_APPS =['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','chat','channels',]

ASGI_APPLICATION ='myapp.asgi.application'

CHANNEL_LAYERS ={"default":{"BACKEND":"channels.layers.InMemoryChannelLayer",}}

Tạo routing.pyconsumers.py trong myapp

myapp
├─ myapp
│  ├─ __init__.py
│  ├─ asgi.py
│  ├─ consumers.py
│  ├─ routing.py
│  ├─ settings.py
│  ├─ urls.py
│  └─ wsgi.py
├─ chat
│  ├─ __init__.py
│  ├─ admin.py
│  ├─ apps.py
│  ├─ models.py
│  ├─ tests.py
│  ├─ urls.py
│  └─ views.py
├─ templates
│  └─ chat.html
└─ manage.py

Chỉnh sửa fie asgi.py trong myapp

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from myapp import routing

os.environ.setdefault('DJANGO_SETTINGS_MODULE','myapp.settings')

application = ProtocolTypeRouter({"http": get_asgi_application(),"websocket": AuthMiddlewareStack(
        URLRouter(
            routing.ws_urlpatterns
        ))})

Chỉnh sửa file routing.py tron myapp

from django.urls import path

from.import consumers

ws_urlpatterns =[
    path('ws/chat/<str:room_name>/', consumers.ChatConsumer.as_asgi()),]

Chỉnh sửa file consumers.py trong myapp

import json
from channels.generic.websocket import AsyncWebsocketConsumer

classChatConsumer(AsyncWebsocketConsumer):asyncdefconnect(self):print('connect')await self.accept()
        room_name = self.scope['url_route']['kwargs']['room_name']await self.channel_layer.group_add(room_name, self.channel_name)print(f"Kết nối vào nhóm {self.channel_name}")asyncdefreceive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        room_name = self.scope['url_route']['kwargs']['room_name']await self.channel_layer.group_send(
            room_name,{'type':'chat_message',"message": message
            })asyncdefchat_message(self, event):
        message = event['message']await self.send(text_data=json.dumps({'message': message,}))asyncdefdisconnect(self, close_code):
        room_name = self.scope['url_route']['kwargs']['room_name']await self.channel_layer.group_discard(room_name, self.channel_name)print(f"Thoát khỏi nhóm {self.channel_name}")

Tạo và chỉnh sửa file room.html trong templates

myapp
├─ myapp
│  ├─ __init__.py
│  ├─ asgi.py
│  ├─ consumers.py
│  ├─ routing.py
│  ├─ settings.py
│  ├─ urls.py
│  └─ wsgi.py
├─ chat
│  ├─ __init__.py
│  ├─ admin.py
│  ├─ apps.py
│  ├─ models.py
│  ├─ tests.py
│  ├─ urls.py
│  └─ views.py
├─ templates
│  ├─ chat.html
│  └─ room.html
└─ manage.py
<!DOCTYPEhtml><html><head><metacharset="utf-8"/><title>Chat Room</title></head><body><textareaid="chat-log"cols="100"rows="20"></textarea><br><inputid="chat-message-input"type="text"size="100"><br><inputid="chat-message-submit"type="button"value="Send">
    {{ room_name|json_script:"room_name" }}
    <script>const roomName =JSON.parse(document.getElementById('room_name').textContent);const chat =`ws://127.0.0.1:8000/ws/chat/${roomName}/`const chatSocket =newWebSocket(chat)

        chatSocket.onopen=function(e){
            console.log("open", e);}

        chatSocket.onmessage=function(e){const data =JSON.parse(e.data);
            document.querySelector('#chat-log').value +=(data.message +'n');};

        chatSocket.onerror=function(e){
            console.log("error", e)}

        chatSocket.onclose=function(e){
            console.log("close", e)}

        document.querySelector('#chat-message-input').focus();
        document.querySelector('#chat-message-input').onkeyup=function(e){if(e.keyCode ===13){// enter, return
                document.querySelector('#chat-message-submit').click();}};

        document.querySelector('#chat-message-submit').onclick=function(e){const messageInputDom = document.querySelector('#chat-message-input');const message = messageInputDom.value;
            chatSocket.send(JSON.stringify({'message': message
            }));
            messageInputDom.value ='';};</script></body></html>

Run app

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

Chúc các bạn thành công!

Nguồn: viblo.asia

Bài viết liên quan

9 Mẹo lập trình Web “ẩn mình” giúp tiết kiệm hàng giờ đồng hồ

Hầu hết các lập trình viên (kể cả những người giỏi) đều tốn thời gian x

Can GPT-4o Generate Images? All You Need to Know about GPT-4o-image

OpenAI‘s GPT-4o, introduced on March 25, 2025, has revolutionized the way we create visual con

Khi nào nên dùng main, section, article, header, footer, và aside trong HTML5

HTML5 đã giới thiệu các thẻ ngữ nghĩa giúp cấu trúc nội dung web một cách có

So sánh Webhook và API: Khi nào nên sử dụng?

Trong lĩnh vực công nghệ thông tin và phát triển phần mềm, Webhook và API là hai th