Django channels daphne: отсутствует 1 требуемый позиционный аргумент: 'send'
Здравствуйте, у меня проблемы с работой каналов django в продакшене. Я запускаю
gunicorn --bind 0.0.0.0:8000 project_name.asgi
чтобы проверить, что моя настройка ASGI работает правильно (Все это работает на моей локальной машине, что очень странно. Возможно, я что-то упускаю):
Эту ошибку я продолжаю получать :( Я перепробовал все онлайн, но ничего не помогает:
Traceback (most recent call last):
File "/home/quilt/quilt_env/lib/python3.10/site-packages/gunicorn/workers/sync.py", line 136, in handle
self.handle_request(listener, req, client, addr)
File "/home/quilt/quilt_env/lib/python3.10/site-packages/gunicorn/workers/sync.py", line 179, in handle_request
respiter = self.wsgi(environ, resp.start_response)
TypeError: ProtocolTypeRouter.__call__() missing 1 required positional argument: 'send'
В моем файле требований есть следующее:
channels==4.0.0
channels-redis==4.0.0
daphne==4.0.0
Django==4.1.5
billiard==4.1.0
asgiref==3.6.0
Вот мой файл настроек:
ASGI_APPLICATION = 'project_name.asgi.application'
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": ["127.0.0.1", "6379")],
},
},
}
Вот моя установка asgi.py:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project_name.settings')
django.setup()
from channels.security.websocket import AllowedHostsOriginValidator
from channels.routing import ProtocolTypeRouter, URLRouter
from django_channels_jwt_auth_middleware.auth import JWTAuthMiddlewareStack
import notifications.routing
application = ProtocolTypeRouter({
'http': get_asgi_application(),
'websocket': AllowedHostsOriginValidator(
JWTAuthMiddlewareStack(
URLRouter(
notifications.routing.websocket_urlpatterns
),
)
)
})
Вот моя маршрутизация в приложении уведомлений:
from django.urls import path
from notifications import consumers
websocket_urlpatterns = [
path("ws/", consumers.NotificationConsumer.as_asgi()),
]
И вот мой файл consumer.py:
import json
from asgiref.sync import sync_to_async
from channels.exceptions import StopConsumer
from channels.generic.websocket import (
AsyncWebsocketConsumer,
)
from notifications.models import Notifications
class NotificationConsumer(AsyncWebsocketConsumer):
"""
This consumer is used to send notifications.
"""
def __init__(self, *args, **kwargs):
super().__init__(args, kwargs)
self.group_name = ""
self.user = None
@sync_to_async
def get_all_notifications(self):
return list(
Notifications.objects.filter(user=self.user, is_read=False).order_by(
"-created_date"
)[0:10]
)
async def connect(self):
self.group_name = "notification"
self.user = self.scope["user"]
if not self.user.is_authenticated:
return
print("Connected!")
await self.channel_layer.group_add(self.group_name, self.channel_name)
await self.accept()
for notification in await self.get_all_notifications():
await self.send(
text_data=json.dumps(
{
"id": notification.id,
"type_value": notification.type_value(),
"data": notification.serialized_notification_data_json(),
}
)
)
async def disconnect(self, event):
print("closed connection")
print("Close code = ", event)
await self.close()
raise StopConsumer
async def receive_json(self, content, **kwargs):
print(content)
return super().receive(text_data=json.dumps(content), **kwargs)
async def notification_send(self, event):
await self.send(
text_data=json.dumps({
"id": event["message"]["id"],
"type_value": event["message"]["type_value"],
"data": event["message"]["data"],
})
)