پلتفرم Django
(Django Platform)وبسوکت در برنامههای Django
وبسوکت یا WebSocket یک فناوری ارتباطی در وب است که به سرور و مرورگر اجازه میدهد از طریق یک اتصال دوطرفه دائمی، دادهها را به صورت تعاملی ارسال و دریافت کنند. در واقع مرورگر میتواند دادهها را بفرستد و دریافت کند بدون اینکه نیازی به بارگیری دوباره صفحه وب (refresh) باشد. این ویژگی به برنامههای تعاملی مانند چتهای زنده و بازیهای آنلاین کمک میکند.
در ادامه، به نحوه ایجاد برنامه WebSocket در پلتفرم جنگو با استفاده از ماژولchannels و همچنین نحوه استقرار آن در لیارا خواهیم پرداخت.
فهرست عناوین:
در صورتی که تمایلی به خواندن آموزش متنی ندارید میتوانید ویدیوی آموزشی زیر را مشاهده کنید.
ساخت برنامه WebSocket در جنگو
در ابتدا، باید با استفاده از دستور زیر، در یک محیط مجازی، یک پروژه Django جدید ایجاد کنید. پروژه ما، یک چتروم ساده است که بر اصول WebSocket تکیه کرده است:
django-admin startproject ChatApp
پس از اجرای دستور فوق، کافیست تا دستور زیر را اجرا کنید تا ماژولهای channels و daphne برایتان نصب شود:
pip install channels daphne
حال، بایستی با استفاده از دستور زیر، یک application جدید به نام chat در پروژه ایجاد کنید:
python manage.py startapp chat
پس از اجرای دستورات فوق، کافیست تا برنامه chat و ماژولهای channels و daphne را به INSTALLED_APPS در فایل settings.py به شکل زیر، اضافه کنید:
INSTALLED_APPS = [
'daphne',
'chat',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
]
پس از انجام کار فوق، باید قطعه کد زیر را در فایل settings.py قرار دهید:
ASGI_APPLICATION = 'ChatApp.asgi.application'
سپس، فایلها و دایرکتوریهای زیر را در مسیرهای مشخص شده، ایجاد کنید:
- فایل chat/urls.py
- دایرکتوری chat/templates
- دایرکتوری chat/templates/chat
- فایلهای chat/templates/chat/chatPage.html و chat/templates/chat/LoginPage.html
- فایل chat/routing.py
- فایل chat/consumers.py
اکنون، در فایل ChatApp/urls.py قطعه کد زیر را قرار دهید:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path("", include("chat.urls")),
]
و قطعه کد زیر را نیز در chat/urls.py قرار دهید:
from django.urls import path, include
from chat import views as chat_views
from django.contrib.auth.views import LoginView, LogoutView
urlpatterns = [
path("", chat_views.chatPage, name="chat-page"),
# login-section
path("auth/login/", LoginView.as_view
(template_name="chat/LoginPage.html"), name="login-user"),
path("auth/logout/", LogoutView.as_view(), name="logout-user"),
]
سپس، در chat/views.py قطعه کد زیر را قرار دهید:
from django.shortcuts import render, redirect
def chatPage(request, *args, **kwargs):
if not request.user.is_authenticated:
return redirect("login-user")
context = {}
return render(request, "chat/chatPage.html", context)
اکنون، میتوانید در chat/templates/chat/chatPage.html از قطعه کد ساده زیر استفاده کنید:
<!DOCTYPE html>
<html>
<body>
<center><h1>Welcome to chat site! {{request.user}}</h1></center>
<br>
{% if request.user.is_authenticated %}
<center> Logout the chat Page <a href = "{% url 'logout-user' %}">Logout</a></center>
{% endif %}
<div
class="chat__item__container"
id="id_chat_item_container"
style="font-size: 20px"
>
<br />
<input type="text" id="id_message_send_input" />
<button type="submit" id="id_message_send_button">Send Message</button>
<br />
<br />
</div>
<script>
const chatSocket = new WebSocket("ws://" + window.location.host + "/");
chatSocket.onopen = function (e) {
console.log("The connection was setup successfully !");
};
chatSocket.onclose = function (e) {
console.log("Something unexpected happened !");
};
document.querySelector("#id_message_send_input").focus();
document.querySelector("#id_message_send_input").onkeyup = function (e) {
if (e.keyCode == 13) {
document.querySelector("#id_message_send_button").click();
}
};
document.querySelector("#id_message_send_button").onclick = function (e) {
var messageInput = document.querySelector(
"#id_message_send_input"
).value;
chatSocket.send(JSON.stringify({ message: messageInput, username : "{{request.user.username}}"}));
};
chatSocket.onmessage = function (e) {
const data = JSON.parse(e.data);
var div = document.createElement("div");
div.innerHTML = data.username + " : " + data.message;
document.querySelector("#id_message_send_input").value = "";
document.querySelector("#id_chat_item_container").appendChild(div);
};
</script>
</body>
</html>
و همچنین، قطعه کد زیر را در chat/templates/chat/LoginPage.html به کار ببرید:
<!DOCTYPE html>
<html>
<body>
<form method ="post">
{% csrf_token %}
{{form.as_p}}
<br>
<button type = "submit">Login</button>
</form>
</body>
</html>
پس از انجام کارهای فوق، کافیست تا دستورات زیر را اجرا کنید:
python manage.py makemigrations
python manage.py migrate
اکنون، باید قطعه کد زیر را در chat/routing.py قرار دهید:
from django.urls import path , include
from chat.consumers import ChatConsumer
# Here, "" is routing to the URL ChatConsumer which
# will handle the chat functionality.
websocket_urlpatterns = [
path("" , ChatConsumer.as_asgi()) ,
]
و همچنین در chat/consumers.py قطعه کد زیر را قرار دهید:
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.roomGroupName = "group_chat_gfg"
await self.channel_layer.group_add(
self.roomGroupName ,
self.channel_name
)
await self.accept()
async def disconnect(self , close_code):
await self.channel_layer.group_discard(
self.roomGroupName ,
self.channel_layer
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json["message"]
username = text_data_json["username"]
await self.channel_layer.group_send(
self.roomGroupName,{
"type" : "sendMessage" ,
"message" : message ,
"username" : username ,
})
async def sendMessage(self , event) :
message = event["message"]
username = event["username"]
await self.send(text_data = json.dumps({"message":message ,"username":username}))
پس از انجام کارهای فوق، اکنون کافیست تا در ChatApp/asgi.py قطعه کد زیر را قرار دهید:
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ChatApp.settings')
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter , URLRouter
from chat import routing
application = ProtocolTypeRouter(
{
"http" : get_asgi_application() ,
"websocket" : AuthMiddlewareStack(
URLRouter(
routing.websocket_urlpatterns
)
)
}
)
در ادامه، باید قطعه کد زیر را به فایل settings.py اضافه کنید:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer"
}
}
در نهایت، قطعه کد زیر را به انتهای فایل settings.py اضافه کنید:
LOGIN_REDIRECT_URL= "chat-page"
LOGOUT_REDIRECT_URL= "login-user"
تمام کارها انجام شده است و اکنون میتوانید با استفاده از دستور زیر؛ کاربران مدنظر خود را ایجاد کنید تا در چتروم، با یکدیگر تعامل داشته باشند:
python manage.py createsuperuser
در انتها، با استفاده از دستور زیر، میتوانید برنامه را اجرا و استفاده کنید:
python manage.py runserver
استقرار برنامه Django WebSocket در لیارا
برای استقرار برنامههای وبسوکت جنگو در لیارا، نیازی به انجام تغییر خاصی نیست. صرفاً باید به جای استفاده از آدرس ws، عبارت wss را به کار ببرید تا اتصال، ایمن و سازگار باشد. همچنین، در فایل settings.py باید قطعه کد زیر را حذف کنید:
WSGI_APPLICATION = 'ChatApp.wsgi.application'
و به جای آن، از قطعه کد زیر استفاده کنید:
ASGI_APPLICATION = 'ChatApp.asgi.application'
از آنجایی که استفاده از InMemoryChannelLayer در حالت Production، احتمال نشت دادهها را بسیار افزایش میدهد؛ پس بهتر است به جای آن، از Redis Channels استفاده کنید. برای این کار نیز، کافیست تا در ابتدا ماژول channels-redis در پروژه خود، نصب کنید:
pip install channels-redis
پس از نصب ماژول فوق، کافیست تا قطعه کد زیر را از فایل settings.pyحذف کنید:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer"
}
}
و قطعه کد زیر را جایگزین آن کنید:
import os
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer",
"CONFIG": {
"hosts":[{
"address": os.getenv('REDIS_URI'),
}]}
}
}
در انتها، میتوانید برنامه خود را بدون هیچ مشکل خاصی، در لیارا مستقر کنید.
متوجه شدم، برو گام بعدی!