前言
该网上聊天室基于Django,实现了用户登录、创建群聊、加入群聊等功能。用到的技术主要是websocket,前端采用js、html、css编写,为解决每次刷新页面websocket会断开的问题,这里把与websocket连接的相关信息存储到mysql数据库中(这是在本人当前水平下,想到的较好的实现方法,如果有更好的实现方式欢迎到评论区下方评论。
实现过程中的代表性问题
24小时内再次进入群聊能够自动识别用户
也就是说24小时内,如果用户重新进加入过的群聊,仍然可以看到以前的群聊消息,并向群聊里的所有用户暴露id信息。这里使用session机制解决,用户登录成功后把session的生存时间设置为24小时,(提示:这里在mysql数据库中建立三张表如下图所示,为了赶作业这里就不加约束关系了)。
#消息表
class Message(models.Model):
uid = models.CharField(max_length=20, verbose_name="用户名")
msg = models.CharField(max_length=1024, verbose_name="消息")
time = models.DateTimeField(auto_now_add=True,verbose_name="时间")
gid = models.CharField(max_length=20, verbose_name="房间号")
session_key = models.CharField(max_length=80, verbose_name="sessionid")
#用户表
class User(models.Model):
uid = models.CharField(max_length=20, verbose_name="用户名")
pwd = models.CharField(max_length=255, verbose_name="密码")
this_time = models.DateTimeField(verbose_name="本次登录时间")
last_time = models.DateTimeField(verbose_name="上次登录时间")
#websocket连接表
class Websocket(models.Model):
key = models.CharField(max_length=80, verbose_name="websocket连接")
uid = models.CharField(max_length=20, verbose_name="用户名")
gid = models.CharField(max_length=20, verbose_name="房间号")
如果用户要加入或创建的群聊号在Message表中存在,并且后端获取到的session_id(这个session_id是处理过的)在数据库中存在,那么就从Message表select出该群聊里的所有数据传到前端。使用同一个浏览器多次访问相同的url,后端获取的session_id是相同的,即使你在同一个浏览器登录不同的账号,前面提到经过处理的session_id就是把该浏览器对应的session_id和登录用户的uid进行拼接。但这会引起一个问题,用户换一个浏览器进加入过的群聊将不能查看历史记录。
每次刷新页面websocket会断开
小弟不才感觉这是个有点棘手的问题,每次刷新页面后websocket断开连接,那么用户不能在一个群聊里持续通话。最开始用到了localStorage,这个东西好像是每一个浏览器有一个,不同浏览器之间不能共享,敲完代码后发现不仅逻辑有问题还有bug。后来想到了用数据库,把与websocket连接相关的信息存到数据库里,如下图所示,若用户退出群聊就从Websocket表中删除对应的记录。
接下来要做的是,每次刷新页面后从Websocket表中select出与当前登录用户相关的数据,根据uid和gid重新建立websocket连接,因为uid+gid能唯一确定一个websocket连接。
Django中的配置
基于pycharm的具体配置过程可以参考14-9 django中配置channels_哔哩哔哩_bilibili这个视频,或者查看官方文档Django Channels — Channels 4.0.0 documentation。另外该聊天室用到了mysql数据库,需要在setting.py文件中做如下配置,配置中的chatroom是数据库的名字需要手动创建。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'chatroom',
'USER': 'root',
'PASSWORD': 'mysql数据库密码',
'HOST': '127.0.0.1',
'PORT': 3306,
}
}
如果有django4启动时一直没有启动asgi的:
1、安装channels4
2、安装daphe
3、更新daphe版本
3、更新daphne版本 ( pip install -U channels ["daphne"] )
4、确保daphe在settings.py的install_apps的首行
实现结果
实现代码
GitHub - zhgjt/Online-Chatroom: Online Chatroom based on Django