قابلیتهای بلادرنگ را در پروژههای جنگو خود با کانالهای جنگو و وبسوکتها فعال کنید. این راهنمای جامع، یک آموزش گام به گام از پیادهسازی، بهترین روشها و تکنیکهای پیشرفته را ارائه میدهد.
کانالهای جنگو پایتون: راهنمای جامع پیادهسازی WebSocket
در چشمانداز وب امروزی، برنامههای بلادرنگ دیگر یک تجمل نیستند، بلکه یک ضرورت هستند. از برنامههای چت زنده و ابزارهای ویرایش مشارکتی گرفته تا بازیهای آنلاین و داشبوردهای داده بلادرنگ، تقاضا برای ارتباطات و بهروزرسانیهای فوری همواره در حال افزایش است. خوشبختانه، فریمورک جنگو پایتون یک راهحل قدرتمند برای ساخت چنین برنامههایی ارائه میدهد: کانالهای جنگو.
این راهنما یک بررسی جامع از کانالهای جنگو و پیادهسازی WebSocket آن ارائه میدهد. ما به مفاهیم اصلی خواهیم پرداخت، یک مثال عملی را بررسی خواهیم کرد و در مورد تکنیکهای پیشرفته بحث خواهیم کرد تا به شما کمک کند برنامههای بلادرنگ قوی و مقیاسپذیری را با جنگو ایجاد کنید.
درک کانالهای جنگو
کانالهای جنگو قابلیتهای جنگو را فراتر از چرخه درخواست-پاسخ سنتی گسترش میدهد و ارتباط ناهمگام و اتصالات پایدار را فعال میکند. این کار را با معرفی رابط دروازه سرور ناهمگام (ASGI)، یک جانشین معنوی برای WSGI (رابط دروازه سرور وب)، رابط همگام سنتی جنگو، به دست میآورد.
مفاهیم کلیدی
- ASGI (رابط دروازه سرور ناهمگام): ASGI یک رابط استاندارد بین برنامههای وب پایتون ناهمگام و سرورها است. این به جنگو اجازه میدهد اتصالات طولانیمدت مانند WebSockets را که برای مدت طولانی باز میمانند، مدیریت کند.
- لایههای کانالها: لایههای کانالها یک ستون فقرات ارتباطی برای توزیع پیامها بین بخشهای مختلف برنامه شما فراهم میکنند. آن را به عنوان یک صف پیام یا یک سیستم انتشار/اشتراک در نظر بگیرید. پیادهسازیهای رایج شامل Redis، لایههای کانال در حافظه برای توسعه و سرویسهای پیامرسانی مبتنی بر ابر است.
- مصرفکنندگان: مصرفکنندگان، همتایان ناهمگام نمایههای جنگو هستند. آنها پیامهای ورودی را مدیریت میکنند و بر اساس محتوای پیام، اقدامات را انجام میدهند. مصرفکنندگان میتوانند به عنوان توابع یا کلاسها نوشته شوند و انعطافپذیری و قابلیت استفاده مجدد را ارائه میدهند.
- مسیریابی: مسیریابی نحوه مسیریابی پیامهای ورودی به مصرفکنندگان خاص را تعریف میکند. این شبیه مسیریابی URL جنگو است، اما برای اتصالات WebSocket.
راهاندازی پروژه جنگو شما با کانالها
بیایید با راهاندازی یک پروژه جنگو و نصب کانالهای جنگو شروع کنیم. این بخش فرض میکند که شما پایتون و جنگو را نصب کردهاید.
1. ایجاد یک پروژه جدید جنگو
ترمینال خود را باز کنید و یک پروژه جدید جنگو ایجاد کنید:
django-admin startproject myproject
cd myproject
2. ایجاد یک محیط مجازی (توصیه میشود)
همیشه یک روش خوب این است که یک محیط مجازی برای ایزوله کردن وابستگیهای پروژه خود ایجاد کنید:
python3 -m venv venv
source venv/bin/activate # On Linux/macOS
.\venv\Scripts\activate # On Windows
3. نصب کانالهای جنگو
کانالهای جنگو و وابستگیهای آن را با استفاده از pip نصب کنید:
pip install channels daphne
Daphne یک سرور ASGI است که ما از آن برای اجرای برنامه کانالهای خود استفاده خواهیم کرد. سایر سرورهای ASGI مانند uvicorn نیز سازگار هستند.
4. پیکربندی تنظیمات جنگو
فایل `settings.py` پروژه خود را باز کنید و `channels` را به لیست `INSTALLED_APPS` اضافه کنید:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
# Your other apps
]
پیکربندی برنامه ASGI را به `settings.py` اضافه کنید:
ASGI_APPLICATION = 'myproject.asgi.application'
این به جنگو میگوید از برنامه ASGI تعریف شده در `myproject/asgi.py` استفاده کند.
5. پیکربندی لایه کانالها
لایه کانالها را در `settings.py` پیکربندی کنید. برای توسعه، میتوانید از لایه کانال درون حافظه استفاده کنید. برای تولید، Redis یک انتخاب رایج است. ما برای این مثال از Redis استفاده خواهیم کرد. اطمینان حاصل کنید که Redis بر روی سیستم شما نصب و در حال اجرا است.
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
اگر `channels_redis` نصب نکردهاید، آن را نصب کنید:
pip install channels_redis
6. ایجاد asgi.py
اگر وجود ندارد، یک فایل `asgi.py` در دایرکتوری پروژه خود (در کنار `wsgi.py`) ایجاد کنید. این فایل برنامه ASGI را تعریف میکند:
# myproject/asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import chat.routing # Import your app's routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
chat.routing.websocket_urlpatterns
)
),
})
ساخت یک برنامه چت ساده
بیایید یک برنامه چت ساده بسازیم تا کانالهای جنگو و WebSockets را نشان دهیم. این مثال به کاربران اجازه میدهد پیامها را در یک اتاق چت واحد ارسال و دریافت کنند.
1. ایجاد یک برنامه جنگو جدید
یک برنامه جنگو جدید به نام `chat` ایجاد کنید:
python manage.py startapp chat
`chat` را به لیست `INSTALLED_APPS` در `settings.py` اضافه کنید:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'chat',
# Your other apps
]
2. تعریف مسیریابی WebSocket
یک فایل `routing.py` در برنامه `chat` ایجاد کنید تا مسیریابی WebSocket را تعریف کنید:
# chat/routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
این یک مسیر برای اتصالات WebSocket به `/ws/chat/
3. ایجاد یک مصرفکننده
یک فایل `consumers.py` در برنامه `chat` ایجاد کنید تا `ChatConsumer` را تعریف کنید:
# chat/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async
from django.contrib.auth.models import User
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = f'chat_{self.room_name}'
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
username = text_data_json['username'] # Extract username from the received data
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat.message',
'message': message,
'username': username,
}
)
# Receive message from room group
async def chat_message(self, event):
message = event['message']
username = event['username']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message,
'username': username,
}))
این مصرفکننده، اتصالات WebSocket را مدیریت میکند، به اتاقهای چت میپیوندد و آنها را ترک میکند، پیامها را از مشتریان دریافت میکند و پیامها را به گروه اتاق پخش میکند. مهمتر از همه، این ناهمگام است و به آن اجازه میدهد تا چندین اتصال را همزمان مدیریت کند.
4. ایجاد یک الگو ساده
یک فایل `templates/chat/room.html` در پروژه خود ایجاد کنید. ممکن است لازم باشد دایرکتوری `templates` را در دایرکتوری ریشه پروژه خود و سپس دایرکتوری `chat` را در داخل آن ایجاد کنید. این الگو، اتاق چت را نمایش میدهد و به کاربران اجازه میدهد پیام ارسال کنند.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Chat Room</title>
</head>
<body>
<h1>Chat Room: {{ room_name }}</h1>
<div id="chat-log"></div>
<input type="text" id="chat-message-input" size="100"/><br/>
<input type="text" id="chat-username-input" size="100" placeholder="Enter your username"/><br/>
<button id="chat-message-submit">Send</button>
<script>
const roomName = {{ room_name|json_script:"room-name" }};
const chatSocket = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/chat/'
+ roomName
+ '/'
);
chatSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
document.querySelector('#chat-log').value += (data.username + ': ' + data.message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
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 usernameInputDom = document.querySelector('#chat-username-input');
const message = messageInputDom.value;
const username = usernameInputDom.value; // Get the username
chatSocket.send(JSON.stringify({
'message': message,
'username': username
}));
messageInputDom.value = '';
};
</script>
</body>
</html>
این الگو از جاوا اسکریپت برای ایجاد یک اتصال WebSocket، ارسال پیام و نمایش پیامهای دریافت شده در عنصر `chat-log` استفاده میکند. اکنون همچنین شامل یک فیلد ورودی نام کاربری است و نام کاربری را با هر پیام ارسال میکند.
5. ایجاد یک نما
یک فایل `views.py` در برنامه `chat` ایجاد کنید تا یک نما تعریف کنید که الگوی اتاق چت را رندر میکند:
# chat/views.py
from django.shortcuts import render
def room(request, room_name):
return render(request, 'chat/room.html', {
'room_name': room_name
})
6. تعریف الگوهای URL
URLهای برنامه چت را در فایل `urls.py` پروژه خود قرار دهید:
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('chat/', include('chat.urls')),
]
یک فایل `urls.py` در برنامه `chat` ایجاد کنید:
# chat/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<str:room_name>/', views.room, name='room'),
]
7. اجرای سرور توسعه
سرور توسعه جنگو را با Daphne راهاندازی کنید:
python manage.py runserver
مرورگر وب خود را باز کنید و به `http://127.0.0.1:8000/chat/myroom/` بروید (به جای `myroom` نام اتاق چت مورد نظر را قرار دهید). شما باید رابط اتاق چت را ببینید. همان URL را در یک پنجره مرورگر دیگر باز کنید تا چندین کاربر را شبیهسازی کنید.
تکنیکهای پیشرفته و بهترین روشها
اکنون که یک برنامه چت اولیه راهاندازی کردهاید، اجازه دهید برخی از تکنیکهای پیشرفته و بهترین روشها را برای ساخت برنامههای بلادرنگ قوی و مقیاسپذیر با کانالهای جنگو بررسی کنیم.
احراز هویت و مجوز
ایمنسازی اتصالات WebSocket شما بسیار مهم است. کانالهای جنگو پشتیبانی داخلی برای احراز هویت و مجوز ارائه میدهد. شما میتوانید از سیستم احراز هویت استاندارد جنگو برای احراز هویت کاربران قبل از اتصال به WebSocket استفاده کنید. `AuthMiddlewareStack` در فایل `asgi.py` شما به طور خودکار کاربران را بر اساس جلسه آنها احراز هویت میکند. شما میتوانید از طریق `self.scope['user']` در مصرفکننده خود به کاربر احراز هویت شده دسترسی داشته باشید.
مثال:
# chat/consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
user = self.scope['user']
if user.is_authenticated:
await self.accept()
else:
await self.close()
برای سناریوهای مجوز پیچیدهتر، میتوانید میانافزار یا بررسیهای سفارشی را در مصرفکنندگان خود پیادهسازی کنید.
مقیاسپذیری و عملکرد
با رشد برنامه شما، مقیاسپذیری به یک نگرانی مهم تبدیل میشود. کانالهای جنگو برای مقیاسپذیری طراحی شدهاند، اما باید چندین عامل را در نظر بگیرید:
- لایه کانالها: یک لایه کانال قوی و مقیاسپذیر مانند Redis یا یک سرویس پیامرسانی مبتنی بر ابر مانند Amazon MQ یا Google Cloud Pub/Sub انتخاب کنید. Redis یک نقطه شروع خوب است، اما برای برنامههای پر ترافیک، یک راهحل ابری مدیریت شده را در نظر بگیرید.
- سرور ASGI: از یک سرور ASGI آماده تولید مانند Daphne یا Uvicorn استفاده کنید. این سرورها برای مدیریت تعداد زیادی از اتصالات همزمان به طور موثر طراحی شدهاند.
- مقیاسبندی افقی: چندین نمونه از برنامه جنگو خود را پشت یک موازنهکننده بار مستقر کنید تا حجم کاری را توزیع کنید. هر نمونه باید به همان لایه کانالها متصل شود.
- بهینهسازی پایگاه داده: اگر برنامه شما شامل تعاملات پایگاه داده است، کوئریهای پایگاه داده خود را بهینه کنید و استفاده از کش را برای کاهش بار پایگاه داده در نظر بگیرید.
تست
تست برنامههای کانالهای شما برای اطمینان از قابلیت اطمینان و صحت آنها ضروری است. کانالهای جنگو ابزارهای تست را برای شبیهسازی اتصالات WebSocket و تأیید رفتار مصرفکنندگان شما فراهم میکند.
مثال:
# chat/tests.py
import pytest
from channels.testing.websocket import WebsocketCommunicator
from chat.consumers import ChatConsumer
@pytest.mark.asyncio
async def test_chat_consumer():
communicator = WebsocketCommunicator(ChatConsumer.as_asgi(), "ws/chat/testroom/")
connected, subprotocol = await communicator.connect()
assert connected
await communicator.send_to(text_data={"message": "Hello", "username": "TestUser"})
response = await communicator.receive_from()
assert response == '{"message":"Hello","username":"TestUser"}'
await communicator.disconnect()
این مثال از `WebsocketCommunicator` برای شبیهسازی اتصال WebSocket به `ChatConsumer` استفاده میکند، یک پیام ارسال میکند و پاسخ را تأیید میکند.
مدیریت خطا
مدیریت خطای قوی برای جلوگیری از خرابی برنامه و ارائه یک تجربه کاربری خوب بسیار مهم است. در مصرفکنندگان خود مدیریت خطای مناسب را پیادهسازی کنید تا استثناها را بگیرید و شرایط غیرمنتظره را به درستی مدیریت کنید. شما میتوانید از بلوکهای `try...except` برای گرفتن استثناها و ارسال پیامهای خطا به مشتریان استفاده کنید.
مثال:
# chat/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def receive(self, text_data):
try:
text_data_json = json.loads(text_data)
message = text_data_json['message']
username = text_data_json['username']
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat.message',
'message': message,
'username': username
}
)
except Exception as e:
await self.send(text_data=json.dumps({
'error': str(e)
}))
ملاحظات استقرار
استقرار برنامههای کانالهای جنگو نیازمند برنامهریزی و بررسی دقیق است. در اینجا چند جنبه کلیدی وجود دارد که باید در نظر داشته باشید:
- سرور ASGI: از یک سرور ASGI درجه تولید مانند Daphne یا Uvicorn استفاده کنید. سرور را پیکربندی کنید تا تعداد زیادی از اتصالات همزمان را مدیریت کند و عملکرد را بهینه کند.
- لایه کانالها: یک لایه کانال قابل اعتماد و مقیاسپذیر انتخاب کنید. Redis یک گزینه خوب برای برنامههای کوچک تا متوسط است، اما برای برنامههای بزرگتر، یک سرویس پیامرسانی مبتنی بر ابر را در نظر بگیرید. اطمینان حاصل کنید که لایه کانالهای شما به درستی پیکربندی و ایمن شده است.
- تعادل بار: از یک موازنهکننده بار برای توزیع ترافیک در چندین نمونه از برنامه جنگو خود استفاده کنید. این عملکرد را بهبود میبخشد و از در دسترس بودن بالا اطمینان حاصل میکند.
- نظارت: نظارت جامع را برای ردیابی عملکرد برنامه خود و شناسایی مسائل احتمالی پیادهسازی کنید. تعداد اتصالات WebSocket فعال، توان عملیاتی پیام و نرخ خطا را نظارت کنید.
- امنیت: اتصالات WebSocket خود را با استفاده از رمزگذاری SSL/TLS ایمن کنید. مکانیسمهای احراز هویت و مجوز مناسب را برای محافظت از برنامه خود در برابر دسترسی غیرمجاز پیادهسازی کنید.
موارد استفاده فراتر از برنامههای چت
در حالی که مثال ما بر یک برنامه چت متمرکز بود، کانالهای جنگو متنوع هستند و میتوانند برای طیف گستردهای از برنامههای بلادرنگ اعمال شوند. در اینجا چند نمونه آورده شده است:
- داشبوردهای داده بلادرنگ: بهروزرسانیهای دادههای زنده را در داشبوردها برای نظارت بر عملکرد سیستم، بازارهای مالی یا روندهای رسانههای اجتماعی نمایش دهید. به عنوان مثال، یک پلتفرم معاملات مالی میتواند از کانالهای جنگو برای فشار دادن قیمت سهام در زمان واقعی به کاربران استفاده کند.
- ابزارهای ویرایش مشارکتی: به چندین کاربر اجازه دهید اسناد، صفحات گسترده یا کد را همزمان ویرایش کنند، با تغییراتی که در زمان واقعی منعکس میشوند. یک پلتفرم ویرایش سند مشارکتی شبیه به Google Docs را در نظر بگیرید.
- بازیهای آنلاین: بازیهای چندنفره را با تعاملات بلادرنگ بین بازیکنان بسازید. این میتواند از بازیهای تختهای ساده تا بازیهای اکشن پیچیده متغیر باشد.
- اعلانهای زنده: اعلانهای بلادرنگ را در مورد رویدادها، بهروزرسانیها یا هشدارها به کاربران ارسال کنید. به عنوان مثال، یک پلتفرم تجارت الکترونیک میتواند به کاربران اطلاع دهد که وضعیت سفارش آنها تغییر کرده است.
- برنامههای IoT (اینترنت اشیا): دادهها را از دستگاههای IoT در زمان واقعی جمعآوری و پردازش کنید. یک برنامه خانه هوشمند را تصور کنید که دادههای حسگر را از دستگاههای مختلف دریافت میکند و رابط کاربری را بر این اساس بهروزرسانی میکند.
نتیجه
کانالهای جنگو یک فریمورک قدرتمند و انعطافپذیر برای ساخت برنامههای بلادرنگ با پایتون و جنگو ارائه میدهد. با استفاده از WebSockets، ASGI و لایههای کانالها، میتوانید تجربههای کاربری بسیار تعاملی و جذابی ایجاد کنید. این راهنما یک مرور کلی جامع از کانالهای جنگو ارائه داده است که مفاهیم اصلی، یک مثال عملی و تکنیکهای پیشرفته را پوشش میدهد. همانطور که به کاوش در کانالهای جنگو ادامه میدهید، پتانسیل عظیم آن را برای ساخت برنامههای بلادرنگ نوآورانه و تاثیرگذار کشف خواهید کرد.
قدرت برنامهنویسی ناهمگام را در آغوش بگیرید و پتانسیل کامل پروژههای جنگو خود را با کانالهای جنگو باز کنید!