This project is a case study of using Python Websockets as a websocket backend for Django.
Project description
Django + Websockets
This project is a case study of using Python Websockets as a websocket backend for Django.
It's inspired by Django Channels and aims to provide a seamless transition from it, despite not being an ASGI implementation.
Motivation
Although Django Channels is easy to use and offers excellent performance in single-group or groupless environments, its performance tends to drop significantly in multi-group implementations. This approach uses a RPC transport for communication, eliminating the dependency on a message broker like Redis. Instead, we managed groups using asyncio queues.
Configuration Example
settings.py
# Middleware stack called in each connection
WEBSOCKET_MIDDLEWARE = [
'django_websockets.middlewares.scope.ScopeMiddleware',
'django_websockets.middlewares.auth.AuthMiddleware',
'django_websockets.middlewares.route.RouteMiddleware'
]
# URL mapping module path
WEBSOCKET_ROUTE_MODULE = 'my_project.routing'
# Transport backend
WEBSOCKET_TRANSPORT_BACKENDS = {
'default': {
'BACKEND': 'django_websockets.transport.gGPCTransportLayer',
'CONFIG': {
'address': 'unix:/tmp/example.sock'
}
}
}
my_project/routing.py
from django.urls import re_path
from myapp.websockets import (
InternalChatConsumer
)
urlpatterns = [
re_path(r'/ws/internalchat/?$',
ChatConsumer.as_handler()),
]
myapp/websockets.py
from django_websockets.groups import GroupMessage
from django_websockets.consumers import BaseConsumer
from django_websockets.middlewares.utils import database_sync_to_async
from django_websockets.transport import get_channel_layer
import json
class ChatConsumer(BaseConsumer):
session_started = False
async def connect(self):
# Channels like scope system
self.user = self.scope["user"]
if not await database_sync_to_async(self.user.has_perm)('myapp.connect_to_chat'):
return await self.reject()
self.room_group_name = f'chat_room_a'
self.user_name = self.user.name or self.user.user_name,
await get_channel_layer().group_add(
self.room_group_name,
self
)
session_started = True
async def reject(self):
# Do any cleaning here
await self.close()
async def chat_message(self, event:GroupMessage):
# Params can be used for doing filtering
params = json.loads(event.params)
if params['user_name'] === self.user_name:
return
await self.send(json.dumps({
'from': params['user_name'],
'message': event.message}))
async def receive(self, text_data):
# User was verified?
if self.session_started:
await get_channel_layer().group_send(
self.room_group_name,
GroupMessage(
'chat_message',
message=text_data,
params=json.dumps({'sender': self.user_name})
)
)
Running
Using TCP:
python3 manage.py websockets_server -b localhost:7000 -w 4
Using Unix:
python3 manage.py websockets_server -b unix:/var/run/websockets.sock -w 4
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for django_websockets-0.0.8-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4fb3ee56fb1c3d8376426475f62b41d07ed7f018fde22dc784bee7c02a31d818 |
|
MD5 | a738c4771af8f591b76535b0a8c08bd2 |
|
BLAKE2b-256 | bfefd31b4ea2d881cb330de529040156f5c7629fe12b8500fdaacb73c188f73d |