1,框架DJANGO,VUE
2,前端VUE代码
聊天窗口
{% load static %}
留言窗口
3,后端DJANGO代码
consumers.py
import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
import datetime
class ChatConsumer(WebsocketConsumer):
# websocket建立连接时执行方法
def connect(self):
# 从url里获取聊天室名字,为每个房间建立一个频道组
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# 将当前频道加入频道组
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name
)
# 接受所有websocket请求
self.accept()
# websocket断开时执行方法
def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name
)
# 从websocket接收到消息时执行函数
def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# 发送消息到频道组,频道组调用chat_message方法
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
# 从频道组接收到消息后执行方法
def chat_message(self, event):
message = event['message']
datetime_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 通过websocket发送消息到客户端
self.send(text_data=json.dumps({
'message': f'{datetime_str}:{message}'
}))
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
"""
ASGI config for admin_demo project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
"""
# import os
#
# from django.core.asgi import get_asgi_application
#
# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'admin_demo.settings')
#
# application = get_asgi_application()
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import chat.routing
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "admin_demo.settings")
application = ProtocolTypeRouter({
# http请求使用这个
"http": get_asgi_application(),
# websocket请求使用这个
"websocket": AuthMiddlewareStack(
URLRouter(
chat.routing.websocket_urlpatterns
)
),
})
setting.py 静态文件配置
STATIC_URL = '/static/' STATIC_ROOT = os.path.join(os.path.dirname(__file__),'static') STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ('css',os.path.join(STATIC_ROOT,'css').replace('\\','/') ), ('js',os.path.join(STATIC_ROOT,'js').replace('\\','/') ), ('images',os.path.join(STATIC_ROOT,'images').replace('\\','/') ), ('upload',os.path.join(STATIC_ROOT,'upload').replace('\\','/') ), ) MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR,'media')
#跨域增加忽略 CORS_ALLOW_CREDENTIALS = True # 允许携带Cookie CORS_ORIGIN_ALLOW_ALL = True #channel配置 ASGI_APPLICATION = 'admin_demo.asgi.application' CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'VIEW', ) CORS_ALLOW_HEADERS = ( 'XMLHttpRequest', 'X_FILENAME', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', 'Pragma', )
4,卡点在于前后端websocket接口的用法协调性需要保持一致,后端django怎么单纯的应用vue.js,而不去用原生的jquery(非主流用法)
引用链接Django实战:channels + websocket四步打造个在线聊天室(附动图) - 知乎
此处博主用的是原生写法,我用Vue进行改写
5,大坑之线上部署:
一直出现无法读取asgi_application .网上解决办法都一样。主要原因还是包的原因.parse版本过高。 as_asgi() 问题主要是因为channels版本的问题,目前我用3.0.1就没问题,其他的不太靠谱
python3 -m pip install urllib3==1.26.6