在上一篇文章中,我们借助 Django 3 Channels Redis(Memurai ) 实现了一个网页在线聊天室。
实战 | 使用 Python 开发一个在线聊天室
但是这个聊天室的功能还稍显简陋:
- 不能保存聊天记录,网页一刷新,发的消息都没了。
- 没有用户认证,谁都可以输入房间号、用户名进入。
- 不能发送表情、图片等非文本消息。
今天咱们就来把保存和漫游聊天记录这一功能实现了。
创建数据模型
首先,在 chat 应用下的 models.py 文件中定义一个聊天消息类:
代码语言:javascript复制class Message(models.Model):
username = models.CharField(max_length=255,verbose_name="用户名")
room = models.CharField(max_length=255,verbose_name="聊天室")
content = models.TextField(verbose_name="内容")
create_time = models.DateTimeField(auto_now_add=True,verbose_name="写入时间")
然后执行迁移命令以在数据库中生成数据表:
代码语言:javascript复制python manage.py makemigrations chat
python manage.py migrate
聊天记录存储
有了聊天记录表之后,对于漫游聊天记录的过程就很简单了:
- 第一步,所有用户发送的消息要存储入库;
- 第二步,从数据库中查询聊天记录;
- 第三步,响应给前端进行渲染。
我们首先来处理数据的入库。
之前的代码中,我们在 chat 应用中的 consumers.py 文件中通过 ChatConsumer 这个类来实现 WebSocket 的所有处理。
后端在接收到消息之后直接将消息推送给了对应房间号,现在我们需要加上数据存储的步骤。
首先,在 ChatConsumer 类中新建一个名为 save_msg() 的方法,在这个方法里面我们接收「用户名」、「房间号」、「消息」三个参数,然后将其写入到 Message 数据模型中:
代码语言:javascript复制 # 保存消息
@sync_to_async()
def save_msg(self,username,room,msg):
Message.objects.create(username=username, room=room, content=msg)
sync_to_async 装饰器用于将同步方法转换为异步方法,需要在文件头部引入:
代码语言:javascript复制from asgiref.sync import sync_to_async
保存消息的方法创建好之后,我们在 ChatConsumer 类的 receive() 方法中间进行调用:
代码语言:javascript复制 # 接收消息
async def receive(self, text_data=None, bytes_data=None):
data = json.loads(text_data)
message = data['message']
username = data['username']
room = data['room']
# 发送消息到房间
await self.save_msg(username, room, message)
await self.channel_layer.group_send(
…………
这样,WebSocket 在接收到消息之后,会首先将消息存储到数据库,再推送出去。
聊天记录查询
数据库中有了数据,数据的查询就好办了。
我们在聊天室的视图函数中对指定房间号的历史消息进行查询(chat/views.py):
代码语言:javascript复制# 聊天室
def room(request,room_name):
room_name = room_name
username = request.GET.get('username', '游客')
# 查询历史消息
msgs = Message.objects.filter(room=room_name).order_by('create_time')
return render(request,'room.html',locals())
前端渲染聊天记录
我们现在可以在前端 HTML 模板中渲染聊天记录了。
相关代码如下所示:
代码语言:javascript复制 <!-- 聊天记录 -->
<div id="chat-record">
{% for m in msgs %}
{% if m.username == username %}
<div class="right_msg">{{m.username}}<div class="right-record"><span>{{m.content}}</span></div></div><br>
{% else %}
<div class="left_msg">{{m.username}}<div class="left-record"><span>{{m.content}}</span></div></div><br>
{% endif %}
{% endfor %}
</div>
这样,我们在进入到指定房间的页面后,就会把历史聊天消息给漫游同步。
最终效果如下所示:
总结
在本篇文章中,我们通过 Django 的数据模型实现了聊天室的聊天记录漫游。
在接下来的文章中,我们还将继续对这个使用 Python 开发的在线聊天室进行开发和优化。
比如:
- 用户认证;
- 发送非文本消息;
- 前端 VUE 改造;
敬请期待!