Отсоединение веб-сокета CookieCutter Django (с помощью Docker)
Я пытаюсь создать приложение для чата. Я использую Cookiecutter django в качестве инициатора проекта. Использую среду docker и celery, так как мне нужно использовать redis для связи через websocket. Но websocket постоянно разъединяется, даже если я принимаю соединение с потребителями, используя self.accept()
. Я также включил CHANNEL_LAYERS
в файл config/settings/base.py
.
Вот мой локальный env
файл.
# General
# ------------------------------------------------------------------------------
USE_DOCKER=yes
IPYTHONDIR=/app/.ipython
# Redis
# ------------------------------------------------------------------------------
REDIS_URL=redis://redis:6379/0
REDIS_HOST=redis
REDIS_PORT=6379
# Celery
# ------------------------------------------------------------------------------
# Flower
CELERY_FLOWER_USER=xxxxx
CELERY_FLOWER_PASSWORD=xxxx
Вот мой consumers.py
файл
from channels.generic.websocket import JsonWebsocketConsumer
class ChatConsumer(JsonWebsocketConsumer):
"""
This consumer is used to show user's online status,
and send notifications.
"""
def __init__(self, *args, **kwargs):
super().__init__(args, kwargs)
self.room_name = None
def connect(self):
print("Connected!")
self.room_name = "home"
self.accept()
self.send_json(
{
"type": "welcome_message",
"message": "Hey there! You've successfully connected!",
}
)
def disconnect(self, code):
print("Disconnected!")
return super().disconnect(code)
def receive_json(self, content, **kwargs):
print(content)
return super().receive_json(content, **kwargs)
Вот мой routing.py
файл
from django.urls import path
from chat_dj.chats import consumers
websocket_urlpatterns = [
path('', consumers.ChatConsumer.as_asgi()),
]
Вот мой asgi.py
файл
"""
ASGI config
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/dev/howto/deployment/asgi/
"""
import os
import sys
from pathlib import Path
from django.core.asgi import get_asgi_application
# This allows easy placement of apps within the interior
# chat_dj directory.
ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent
sys.path.append(str(ROOT_DIR / "chat_dj"))
# If DJANGO_SETTINGS_MODULE is unset, default to the local settings
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
# This application object is used by any ASGI server configured to use this file.
django_application = get_asgi_application()
# Import websocket application here, so apps from django_application are loaded first
from config import routing # noqa isort:skip
from channels.routing import ProtocolTypeRouter, URLRouter # noqa isort:skip
application = ProtocolTypeRouter(
{
"http": get_asgi_application(),
"websocket": URLRouter(routing.websocket_urlpatterns),
}
)
Вот мой local.yml
файл
version: '3'
volumes:
chat_dj_local_postgres_data: {}
chat_dj_local_postgres_data_backups: {}
services:
django: &django
build:
context: .
dockerfile: ./compose/local/django/Dockerfile
image: chat_dj_local_django
container_name: chat_dj_local_django
platform: linux/x86_64
depends_on:
- postgres
- redis
volumes:
- .:/app:z
env_file:
- ./.envs/.local/.django
- ./.envs/.local/.postgres
ports:
- "8000:8000"
command: /start
postgres:
build:
context: .
dockerfile: ./compose/production/postgres/Dockerfile
image: chat_dj_production_postgres
container_name: chat_dj_local_postgres
volumes:
- chat_dj_local_postgres_data:/var/lib/postgresql/data:Z
- chat_dj_local_postgres_data_backups:/backups:z
env_file:
- ./.envs/.local/.postgres
docs:
image: chat_dj_local_docs
container_name: chat_dj_local_docs
platform: linux/x86_64
build:
context: .
dockerfile: ./compose/local/docs/Dockerfile
env_file:
- ./.envs/.local/.django
volumes:
- ./docs:/docs:z
- ./config:/app/config:z
- ./chat_dj:/app/chat_dj:z
ports:
- "9000:9000"
command: /start-docs
redis:
image: redis:6
container_name: chat_dj_local_redis
ports:
- "6379:6379"
celeryworker:
<<: *django
image: chat_dj_local_celeryworker
container_name: chat_dj_local_celeryworker
depends_on:
- redis
- postgres
ports: []
command: /start-celeryworker
celerybeat:
<<: *django
image: chat_dj_local_celerybeat
container_name: chat_dj_local_celerybeat
depends_on:
- redis
- postgres
ports: []
command: /start-celerybeat
flower:
<<: *django
image: chat_dj_local_flower
container_name: chat_dj_local_flower
ports:
- "5555:5555"
command: /start-flower
Поскольку я использую react в качестве фронтенда, вот моя часть фронтенда, из которой я пытаюсь подключиться к websocket.
import React from 'react';
import useWebSocket, { ReadyState } from 'react-use-websocket';
export default function App() {
const { readyState } = useWebSocket('ws://127.0.0.1:8000/', {
onOpen: () => {
console.log("Connected!")
},
onClose: () => {
console.log("Disconnected!")
}
});
const connectionStatus = {
[ReadyState.CONNECTING]: 'Connecting',
[ReadyState.OPEN]: 'Open',
[ReadyState.CLOSING]: 'Closing',
[ReadyState.CLOSED]: 'Closed',
[ReadyState.UNINSTANTIATED]: 'Uninstantiated',
}[readyState];
return (
<div>
<span>The WebSocket is currently {connectionStatus}</span>
</div>
);
};
Websocket постоянно отключается, и я не знаю почему. Поскольку я использую машину windows, локально я не могу использовать redis, и я не знаю, что не так с cookiecutter django.