参考:https://channels.readthedocs.io/en/stable/tutorial/index.html
官方文档只是创建了个room,没有昵称,看了示例后自己加了个昵称,这样看的更直观些
先看下效果:
Image.png Image.png
1.安装
djano版本:3.1
python3 -m django --version
3.1
安装channels
pyhton3 -m pip install channels
安装后需要把channels添加到settings.py文件的installapp
2.创建工程
python manage.py startproject mysite
python manage.py startapp chat
chat加入到setting的instalapp
chat目录增加模板文件
templates/
chat/
index.html
<!-- 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="you-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.keyCode === 13) { // enter, return
document.querySelector('#room-name-submit').click();
}
};
document.querySelector('#room-name-submit').onclick = function(e) {
var roomName = document.querySelector('#room-name-input').value;
var userName = document.querySelector('#you-name-input').value;
window.location.pathname = '/chat/' + roomName +'/'+userName;
};
</script>
</body>
</html>
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">
{{ room_name|json_script:"room-name" }}
{{ user_name|json_script:"user-name" }}
<script>
const roomName = JSON.parse(document.getElementById('room-name').textContent);
const userName = JSON.parse(document.getElementById('user-name').textContent);
const chatSocket = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/chat/'
+ roomName
+ '/'+userName+'/'
);
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');
};
document.querySelector('#chat-message-input').focus();
document.querySelector('#chat-message-input').onkeyup = function(e) {
if (e.keyCode === 13) { // 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;
chatSocket.send(JSON.stringify({
'message': message
}));
messageInputDom.value = '';
};
</script>
</body>
</html>
过滤器json_script:
此处意思为生成一个类似页面元素,值就是传过来的值,id为room_name,
这里我加了一个吧用户昵称也传过来
Image.png
2.路由
chat/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<str:room_name>/<str:user_name>', views.room, name='room'),
]
3.视图
from django.shortcuts import render
# Create your views here.
# chat/views.py
def index(request):
return render(request, 'chart/index.html')
def room(request, room_name,user_name):
return render(request, 'chart/room.html', {
'room_name': room_name,
'user_name': user_name
})
4.主路由,mysite/urls.py
path('chat/', include('chart.urls')),
5,mysite/asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import chart.routing
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
chart.routing.websocket_urlpatterns
)
),
})
6.chat/rounting.py
# chat/routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<room_name>\w+)/(?P<user_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
7consumer.py
# chat/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.user_name = self.scope['url_route']['kwargs']['user_name']
self.room_group_name = 'chat_%s' % self.room_name
print('roomname',self.room_name)
print('user_name', self.user_name)
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message':self.user_name+': '+ message
}
)
# Receive message from room group
async def chat_message(self, event):
message = event['message']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message
}))
8.安装redis
docker 安装:
docker run -p 6379:6379 -d redis:5
如果是windows本地安装,注意需要安装5.0版本以上的
否则运行程序时会出现类似:ERR unknown command 'BZPOPMIN'的错误
redis5.0 windows安装
https://blog.csdn.net/qq_26373925/article/details/109269459
https://github.com/tporadowski/redis/releases
安装后启动
安装channels-redis
python3 -m pip install channels_redis
9.# mysite/settings.py
ASGI_APPLICATION = 'mysite.asgi.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
10.启动server,python manage.py run server
image.pngimage.png
使用两台机器,或打开浏览器两个页签,分别输入两同的room名称不同的昵称,就可以开始聊天了
网友评论