Python Programming

إتقان Django Channels: بناء تطبيقات WebSocket في الوقت الفعلي باستخدام Django 5.0

لقد تطور الويب الحديث ليتجاوز دورة الطلب والاستجابة التقليدية. من تطبيقات الدردشة المباشرة ومحررات المستندات التعاونية إلى مؤشرات الأسهم في الوقت الفعلي ولوحات المتصدرين في الألعاب، يتوقع المستخدمون الآن ردود فعل فورية. بينما كان Django لفترة طويلة المعيار الذهبي لتطوير الواجهات الخلفية القوية، كانت طبيعته المتزامنة تجعله أقل ملاءمة لهذه الاتصالات الدائمة طويلة الأمد. هنا يأتي دور Django Channels.

في هذا الدليل، سنستكشف كيف يحول Django 5.0، بالاقتران مع مكتبة Channels، مشروع Django الخاص بك إلى تطبيق ASGI (واجهة بوابة الخادم غير المتزامنة) قادر على التعامل مع WebSockets بكفاءة. صُممت هذه المقالة للمطورين من المستوى المتوسط إلى المتقدم الذين يسعون لسد الفجوة بين عروض Django التقليدية والاتصال في الوقت الفعلي.

فهم البنية: WSGI مقابل ASGI

لإتقان Channels، يجب عليك أولاً فهم تحول البروتوكول الأساسي. تعمل تطبيقات Django القياسية على WSGI، وهو متزامن ولا يحفظ الحالة. كل طلب HTTP يتم التعامل معه ومعالجته ثم يتم قطع الاتصال. ومع ذلك، تتطلب WebSockets اتصالاً دائماً يظل مفتوحاً طوال فترة التفاعل.

تقوم Django Channels بتغليف Django في خادم ASGI، مثل Uvicorn أو Daphne، مما يسمح لها بالتعامل مع WebSockets و HTTP/2 والانتظار الطويل إلى جانب طلبات HTTP القياسية. يحسن Django 5.0 هذا التكامل من خلال دعم أفضل للبرمجة غير المتزامنة في الأدوات الأساسية، مما يجعل الانتقال أكثر سلاسة للمطورين الذين لديهم بالفعل معرفة بمكتبة asyncio في Python.

إعداد بيئة العمل

قبل الغوص في الكود، تأكد من امتلاكك لمشروع Django 5.0 نظيف. ستحتاج إلى تثبيت مكتبة Channels وخادم ASGI. للإنتاج، يُوصى بشدة باستخدام Uvicorn نظراً لأدائه.

pip install channels uvicorn gunicorn

في ملف settings.py، تحتاج إلى إضافة 'channels' إلى INSTALLED_APPS وتكوين تطبيق ASGI. يخبر هذا Django باستخدام Channels كنقطة دخول للاتصالات الواردة.

# settings.py

INSTALLED_APPS = [
    # ...
    'channels',
]

ASGI_APPLICATION = 'myproject.asgi.application'

إنشاء مستهلك WebSocket

في نظام Django البيئي، يُسمى معالج WebSocket "مستهلكاً" (Consumer). المستهلكون مماثلون لعروض Django (Views) ولكنهم غير متزامنين بطبيعتهم. دعنا ننشئ مستهلكاً بسيطاً يقبل اتصال WebSocket ويرسل الرسائل مرة أخرى إلى العميل.

أنشئ ملفاً باسم consumers.py في دليل التطبيق الخاص بك:

# consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = 'general'
        self.room_group_name = f'chat_{self.room_name}'

        # الانضمام إلى مجموعة الغرفة
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )
        await self.accept()

    async def disconnect(self, close_code):
        # مغادرة مجموعة الغرفة
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    # استقبال رسالة من WebSocket
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        # إرسال الرسالة إلى مجموعة الغرفة
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message
            }
        )

    # استقبال رسالة من مجموعة الغرفة
    async def chat_message(self, event):
        message = event['message']

        # إرسال الرسالة إلى WebSocket
        await self.send(text_data=json.dumps({
            'message': message
        }))

يوفر AsyncWebsocketConsumer واجهة نظيفة لإدارة دورة حياة اتصال WebSocket. طريقة connect هي المكان الذي تقوم فيه بمصادقة المستخدمين أو الانضمام إلى غرف محددة (مجموعات). يُعد channel_layer العمود الفقري لـ Channels، مما يسمح لعمليات مختلفة بالتواصل.

توجيه WebSockets

تماماً كما تقوم بتوجيه عناوين URL الخاصة بـ HTTP إلى العروض، يجب عليك توجيه عناوين URL الخاصة بـ WebSockets إلى المستهلكين. أنشئ ملف routing.py في تطبيقك:

# routing.py
from django.urls import re_path
from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P\w+)/$', consumers.ChatConsumer.as_asgi()),
]

ثم، في ملف asgi.py الخاص بمشروعك، قم بتضمين هذه المسارات:

# myproject/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import chat.routing

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

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

الخاتمة

يوفر Django 5.0 و Django Channels إطار عمل قوي وموحد لبناء تطبيقات كاملة النطاق في الوقت الفعلي. من خلال الاستفادة من الكود غير المتزامن وطبقة القنوات، يمكنك بناء ميزات معقدة مثل الإشعارات المباشرة وألعاب اللاعبين المتعددين والأدوات التعاونية دون التخلي عن فوائد الأمان و ORM الخاصة بـ Django. بينما تستمر في الاستكشاف، فكر في دمج Redis كخلفية لطبقة القنوات من أجل قابلية التوسع في بيئات الإنتاج. سيؤدي إتقان هذه الأدوات إلى توسيع قدراتك بشكل كبير كمطور واجهة خلفية في Python.

Share: