Django

⌘K
  1. Home
  2. Django
  3. Django তে কিভাবে কাজ করতে...
  4. Channels

Channels

Django Channels টিউটোরিয়াল পার্টসমূহ

  1. পার্ট ১: Django Channels এর ভূমিকা এবং মৌলিক ধারণা
    • Django Channels কী এবং কেন এটি দরকার।
    • Django এর Request-Response মডেলের সাথে Channels এর পার্থক্য এবং প্রয়োজনীয়তা।
  2. পার্ট ২: Django Channels সেটআপ এবং ইনস্টলেশন
    • Django প্রজেক্টে Channels সেটআপ করার স্টেপ-বাই-স্টেপ গাইড।
    • Redis ইনস্টলেশন এবং Django Channels এর সাথে একত্রে সেটআপ করা।
  3. পার্ট ৩: ASGI এবং Django ASGI Application
    • ASGI (Asynchronous Server Gateway Interface) কী এবং এটি কীভাবে Django তে কাজ করে।
    • Django এর ASGI application তৈরি এবং এটি নিয়ে কাজ করা।
  4. পার্ট ৪: WebSocket Protocol এবং Channels এর মাধ্যমে WebSocket ব্যবহারের প্রাথমিক ধারণা
    • WebSocket কী এবং HTTP এর সাথে এর পার্থক্য।
    • Django Channels দিয়ে WebSocket তৈরি এবং কানেকশন ম্যানেজ করা।
  5. পার্ট ৫: Consumer তৈরির মৌলিক ধারণা
    • Consumer কী এবং Django Channels এ Consumer এর ভূমিকা।
    • Synchronous ও Asynchronous Consumer এর প্রাথমিক ব্যবহার।
  6. পার্ট ৬: WebSocket Consumer দিয়ে Real-time Chat Application তৈরি (Basic)
    • WebSocket Consumer ব্যবহার করে রিয়েল-টাইম চ্যাট এপ্লিকেশন তৈরি।
    • বার্তা প্রেরণ ও গ্রহণের প্রাথমিক উদাহরণ।
  7. পার্ট ৭: Group Communication এবং Broadcast Messaging
    • Group তৈরি করা এবং Group এ বার্তা প্রেরণ করা।
    • Broadcaster এর মাধ্যমে একাধিক ক্লায়েন্টে মেসেজ পাঠানো।
  8. পার্ট ৮: Django ORM এর সাথে Channels ব্যবহার
    • Django ORM এবং ডাটাবেস মডেলকে Channels এর সাথে ইন্টিগ্রেট করা।
    • ডাটাবেস আপডেট করা হলে রিয়েল-টাইম এপ্লিকেশনে পরিবর্তন দেখানো।
  9. পার্ট ৯: Authentication এবং Permissions Channels এ প্রয়োগ
    • Channels এ User Authentication যুক্ত করা এবং লাইভ এপ্লিকেশনে User Permission সেট করা।
    • Anonymous User Management এবং User-Only Communication উদাহরণ।
  10. পার্ট ১০: Redis ব্যবহার করে Channels এর সাথে Caching
    • Redis এর মাধ্যমে Channels এ ডেটা ক্যাশিং এবং Performance বৃদ্ধি করা।
    • Real-time অ্যাপ্লিকেশন এর জন্য ক্যাশিং কৌশল।
  11. পার্ট ১১: Django Channels Middleware
    • Channels Middleware এবং কাস্টম Middleware তৈরি করা।
    • Consumer এ Middleware এর প্রয়োগ এবং কাজের উদাহরণ।
  12. পার্ট ১২: Real-time Notification System তৈরি (Advanced)
    • Django Channels ব্যবহার করে রিয়েল-টাইম Notification System তৈরি।
    • Notification পাঠানোর উদাহরণ এবং এর বিভিন্ন উপায়।
  13. পার্ট ১৩: Task Queue এবং Background Tasks পরিচালনা
    • Background Task ব্যবস্থাপনার জন্য Celery এর সাথে Channels ইন্টিগ্রেশন।
    • Background এ অ্যাসিনক্রোনাস টাস্ক কিউ পরিচালনা করা।
  14. পার্ট ১৪: Channels এবং Django Testing
    • Channels এর Testing এর জন্য বিভিন্ন কৌশল।
    • Channels এর Integration এবং Unit Testing উদাহরণ।
  15. পার্ট ১৫: Channels Deployment এবং Production Setup
    • Channels প্রজেক্ট ডেপ্লয়মেন্টের জন্য সেরা কৌশল।
    • Production পরিবেশে Channels এবং Redis সেটআপ এবং Best Practices।

প্রজেক্ট বানাই

এই পর্বে আমরা একটি প্রজেক্ট বানাচ্ছি এবং একটি চ্যাট পেজ html এ বানিয়ে সেটা রেন্ডার করবো এবং সাবমিট বাটন ক্লিক করলে ইনপুট এর টেক্সট টি অন্য একটি ইউআরএল এ পাঠাবে যেটাকে আমরা চ্যাট রুম হিসাবে জানবো

প্রজেক্ট বানাই

django-admin startproject mysite

এপ্লিকেশন বানাই

python manage.py startapp chat

এই প্রজেক্ট এ কাজের জন্য আমাদের দুইটি ফাইল দরকার হবে chat/views.py ও chat/init.py.অন্য ফাইল গুলো মুছে ফেলি

chat/
    __init__.py
    views.py

আমাদের এপ্লিকেশন টি প্রজেক্টের সাথে যুক্ত করি

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

একটি ভিউ তৈরী করি

এপ্লিকেশন ফোল্ডারে templates ফোল্ডারে index.html নামে একটি ফাইল বানিয়ে ভিউ দিয়ে রিটার্ন করি

# chat/views.py
from django.shortcuts import render


def index(request):
    return render(request, "index.html")

html ফাইলে একটি ইনপুট আছে সাবমিট করলে HOST লোকেশন এর সাথে /CHAT/ইনপুট এ দেয়া নাম্বার এর ইউআরএল এ নিয়ে যাবে

<!-- chat/templates/chat/index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Rooms</title>
</head>
<body>
    What chat room would you like to enter?<br>
    <input id="room-name-input" type="text" size="100"><br>
    <input id="room-name-submit" type="button" value="Enter">

    <script>
        document.querySelector('#room-name-input').focus();
        document.querySelector('#room-name-input').onkeyup = function(e) {
            if (e.key === 'Enter') {  // 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>

urls.py নামে ফাইল বানাই

# chat/urls.py
from django.urls import path

from . import views


urlpatterns = [
    path("", views.index, name="index"),
]

প্রজেক্টের সাথে যুক্ত করি

# mysite/urls.py
from django.contrib import admin
from django.urls import include, path

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

RUN SERVER

python manage.py runserver

Configure

লাইব্রেরি ইনস্টল করি

pip install channels daphne

daphne এবং channel কে ইনস্টল apps এ যোগ করি এবং daphne অবস্যই প্রথম লাইনে রাখবো


INSTALLED_APPS = [
    'daphne'
    'channels', 
       
]


ASGI_APPLICATION = "mysite.asgi.application"

সার্ভার রান করি

python manage.py runserver

দেখতে পারবো asgi daphne শো করছে

চ্যাট রুম বানাই

Create a new file chat/templates/chat/room.html

<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Room</title>
</head>
<body>
    
    <textarea id="chat-log" cols="100" rows="20"></textarea><br>

    <input id="chat-message-input" type="text" size="100"><br>

    <input id="chat-message-submit" type="button" value="Send">

    <script>


        //এন্টার ক্লিক করলে ফরমটি সাবমিট হবে 
        document.querySelector('#chat-message-input').focus();
        document.querySelector('#chat-message-input').onkeyup = function(e) {
            if (e.key === 'Enter') {  // 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;
            
            // কিছু একটা হবে()

            messageInputDom.value = '';
        };
    </script>
</body>
</html>

# chat/views.py
from django.shortcuts import render


def index(request):
    return render(request, "index.html")


def room(request, room_name):
    return render(request, "room.html", {"room_name": room_name})

from django.urls import path

from . import views


urlpatterns = [
    path("", views.index, name="index"),
    path("<str:room_name>/", views.room, name="room"),

]

python manage.py runserver

আমরা যদি আমাদের আগের index route এ ভিজিট করে ফর্ম সাবমিট করি তাহলে room route এ নিয়ে আসবে

ইউআরএল থেকে রুম নাম টি একসেস করি

room.html এ একটি websocket বানাই যা এই ইউআরএল ws://127.0.0.1:8000/ws/chat/lobby/ টি ওপেন করার চেষ্টা করবে। আমাদের room.html এর জাভাস্ক্রিপ্ট সেকশন এ নিচের কোড যোগ করি

        
        const chatSocket = new WebSocket(
            'ws://'
            + window.location.host
            + '/ws/chat/'
            + roomName
            + '/'
        );

সাবমিট ফাংশনটি আপডেট করি সাবমিট করলে আমাদের বানানো websocket যার নাম chatSocket এর মাদ্ধমে ইনপুট সেন্ড করবে

        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 = '';
        };

চ্যাট সকেট মেসেজ হিসাবে যা পাঠাবে তা আমরা টেক্সট এরিয়া তে শো করবো

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

সকেট টি বন্ধ হয়ে গেলে কনসোল এ শো করবে

        chatSocket.onclose = function(e) {
            console.error('Chat socket closed unexpectedly');
        };

Consumer

/ws/chat/ROOM_NAME/ ওয়েবসকেট এর সাথে সংযোগ হওয়ার পর তথ্য আদান প্রদানের জন্য আমাদের cunsumer বানাতে হবে

এপ্লিকেশন ফোল্ডারে একটি ফাইল তৈরী করি consumers.py নামে অন্য নামেও চলবে সমস্যা নেই

# chat/consumers.py
import json

from channels.generic.websocket import WebsocketConsumer


class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    # আমরা ওয়েবসকেট থেকে message নামে ভ্যারিয়েবল এ ডেটা পাঠিয়ে ছিলাম এখন ওই messege নামে আবার সেন্ড   
    # করলাম তারপর আমরা তো আমাদের html websocket এ বলে দিয়েছি আগের textarea তে যে টেক্সট থাকবে তার 
    # সাথে এই মেসেজ যোগ হবে এবং নতুন লাইন যোগ হবে। 
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]

        self.send(text_data=json.dumps({"message": message}))

routing


আমাদের একটি route বানাতে হবে এপ্লিকেশন ফোল্ডারে ws route যা আমরা websocket জাভাস্ক্রিপ্ট এ দিয়েছি

আমরা URL রাউটারে সীমাবদ্ধতার কারণে re_path() ব্যবহার করি।

# 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()),
]

project asgy.py

# mysite/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from chat.routing import websocket_urlpatterns

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

# HTTP এবং WebSocket প্রোটোকলের জন্য কনফিগারেশন
application = ProtocolTypeRouter(
    {
        "http": get_asgi_application(),  # HTTP রিকোয়েস্ট হ্যান্ডল
        "websocket": URLRouter(websocket_urlpatterns),  # WebSocket URL প্যাটার্ন হ্যান্ডল
    }
)

pip install channels_redis

settings.py

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("127.0.0.1", 6379)],
        },
    },
}

# ডেভেলপমেন্ট এর সময় 
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels.layers.InMemoryChannelLayer',  # Use in-memory for development
    },
}

আমাদের consumer.py কে এবার একটু আপডেট করতে হবে

from asgiref.sync import async_to_sync

কানেক্ট হলে

    def connect(self):
        #একটি room ও একটি গ্রুপ বানাতে হবে ইউআরএল থেকে room_name নিয়ে বানাই
        self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
        self.room_group_name = f"chat_{self.room_name}"

        # Join room group
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name, self.channel_name
        )

        self.accept()

self.scope["url_route"]["kwargs"]["room_name"] : প্রত্যেকটা consumer এর একটি ক্ষমতা আছে ইউআরএল থেকে অথবা যদি user লগইন থাকে তাহলে তার থেকে ডেটা গ্রহণ করা এখানে ইউআরএল থেকে ডেটা গ্রহণ করা হয়েছে

self.room_group_name = f"chat_{self.room_name}" : গ্রুপ চ্যানেল করতে চাইলে তার একটি নাম দিতে হয়

ডিস্কানেক্ট হলে

    #disconnect হলে বন্ধ করতে হবে
    def disconnect(self, close_code):
        # Leave room group
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name, self.channel_name
        )

receive হলে

    # Receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]

        # Send message to room group
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name, {"type": "chat.message", "message": message}
        )

    # Receive message from room group
    def chat_message(self, event):
        message = event["message"]

        # Send message to WebSocket
        self.send(text_data=json.dumps({"message": message}))

Articles

How can we help?