网站LOGO
博客 | 棋の小站
页面加载中
12月6日
达尔达尼亚瀑布,博洛尼亚,意大利 ...
网站LOGO 博客 | 棋の小站
记录学习,心得,状态,生活。
菜单
  • 博客 | 棋の小站
    记录学习,心得,状态,生活。
    用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    使用Flask和Redis开发至简聊天程序
    点击复制本页地址
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。
    按住ctrl可打开默认菜单

    使用Flask和Redis开发至简聊天程序

    · 原创 ·
    做做项目 · FlaskRedis
    共 10126 字 · 约 2 分钟 · 292

    今天闲来无聊,想做个小项目练练手,顺便复习一下Flask框架,于是就做了个带有简单的注册和登录功能的聊天网页。

    界面展示

    主页主页登录界面登录界面注册界面注册界面

    以上界面没啥解释的,就是几个简单的界面。

    接下来展示简单的聊天页面。

    聊天界面1聊天界面1

    现在我们还没有输入聊天内容,试试。

    输入未点发送输入未点发送

    点了发送后就会发送到上面去。

    点了发送点了发送

    另开一个浏览器(开谷歌浏览器),注册一个账号,用户名叫qi,然后进入聊天页面。

    图中省略注册和登录,直接登录。

    然后输入聊天内容。

    另一用户输入聊天内容另一用户输入聊天内容

    这就是简简单单的聊天网页。由于Flask框架的简洁性,实现这个功能也很简单。

    关键代码

    后端代码只需要一个app.py便可实现所有功能。

    导入必要的包。

    python 代码:
    import json
    
    from flask import Flask, render_template, request, session, url_for, redirect, flash, jsonify
    from redis import StrictRedis

    实例化Flask应用对象、实例化Redis连接对象,配置密钥(因为用到了消息闪现和session存储用户名)。

    python 代码:
    redis = StrictRedis(host='192.168.204.129', decode_responses=True)
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'qi'

    首页路由,直接渲染模板即可。

    python 代码:
    @app.route('/')
    def index():
        return render_template('html/index.html')

    聊天界面路由,判断Session中是否存储了用户登录的信息,若没有则301到登录页面。

    python 代码:
    @app.route('/chat')
    def chat():
        if session.get('username') is None:
            return redirect(url_for('login'))
        else:
            return render_template('html/chat.html')

    登录路由。若用户已登录则301到聊天页面。

    python 代码:
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if session.get('username') is not None:
            return redirect(url_for('chat'))
        if request.method == 'POST':
            username = request.form['username']
            password = request.form['password']
            password_r = redis.hget('user', username)
            if password_r == password:
                session['username'] = username
                return redirect(url_for('index'))
            else:
                flash('error', '请输入正确的用户名和密码')
        return render_template('html/login.html')

    注册路由。若页面为POST请求则接收参数,加以验证,然后存到数据库里。

    python 代码:
    @app.route('/register', methods=['GET', 'POST'])
    def register():
        if request.method == 'POST':
            username = request.form['username']
            password = request.form['password']
            if redis.hexists('user', username):
                flash('error', '用户名已存在')
            else:
                redis.hset('user', username, password)
                flash('success', '<a href="/login">注册成功!点此跳转到登录页面</a>')
        return render_template('html/register.html')

    获取聊天记录的路由。前端使用Ajax获取请求,因此这里返回消息的列表。

    python 代码:
    @app.route('/recv', methods=['POST'])
    def recv():
        messages = redis.lrange('messages', 0, -1)
        messages = [json.loads(m) for m in messages]
        return jsonify(messages)

    发送消息的路由。也是使用异步发送,所以只提交到数据库即可。

    python 代码:
    @app.route('/send', methods=['POST'])
    def send():
        message = {
            'username': request.json['username'],
            'content': request.json['content']
        }
        redis.rpush('messages', json.dumps(message))
        return jsonify({'status': 'success'})

    最后运行应用对象即可。

    python 代码:
    if __name__ == '__main__':
        app.run()

    前端页面的话首先创建了一个基模板base.html,用block定义了标题区和内容区,将每个页面公共的页面都放到基模板中:

    html 代码:
    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">
        <title>{% block title %}{% endblock %}</title>
        <style>
            body {
                display: flex;
                align-items: center;
                justify-content: center;
                height: 100vh;
                width: 100%;
            }
            .error {
                color: red;
            }
            .success {
                color: green;
            }
            .chat-container {
                max-height: 500px;
                overflow-y: scroll;
            }
            .left-message {
                background-color: #f8f9fa;
            }
            .right-message {
                background-color: #d4edda;
                align-self: flex-end;
            }
            ::-webkit-scrollbar {
                width: 0.5em;
                background-color: #F5F5F5;
            }
            ::-webkit-scrollbar-thumb {
                background-color: #000000;
            }
        </style>
    </head>
    <body>
    {% block content %}
    {% endblock %}
    <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script>
    </body>
    </html>

    随后使每个子模板继承自该模板即可,如登录页面,代码如下:

    html 代码:
    {% extends 'html/base.html' %}
    {% block title %}
        登录 - 聊天程序
    {% endblock %}
    {% block content %}
        <div class="container mt-5">
            <div class="row justify-content-center">
                <div class="col-md-12">
                    <div class="card">
                        <div class="card-header">
                            <h2 class="card-title">登录</h2>
                        </div>
                        <div class="card-body">
                            <form action="/login" method="post">
                                <div class="form-group">
                                    <label for="username">用户名</label>
                                    <input type="text" class="form-control" name="username" id="username"
                                           placeholder="请输入用户名">
                                </div>
                                <div class="form-group">
                                    <label for="password">密码</label>
                                    <input type="password" class="form-control" name="password" id="password"
                                           placeholder="请输入密码">
                                </div>
                                {% with messages = get_flashed_messages(with_categories=True) %}
                                    {% if get_flashed_messages %}
                                        <div class="form-group">
                                            <ul>
                                                {% if messages %}
                                                    {% for message, category in messages %}
                                                        <li class={{ category }}>{{ message }}</li>
                                                    {% endfor %}
                                                {% endif %}
                                            </ul>
                                        </div>
                                    {% endif %}
                                {% endwith %}
                                <button type="submit" class="btn btn-primary">登录</button>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    {% endblock %}

    聊天页面则使用了Ajax向后端发送请求,在接收数据后删除原有节点并添加新节点以实现更新聊天记录的功能;在表单提交后使用Ajax向后端发送请求以更新数据库而不用刷新页面。代码:

    html 代码:
    {% extends 'html/base.html' %}
    {% block title %}聊天页面 - 聊天程序{% endblock %}
    {% block content %}
    
    
        <div class="container mt-5">
            <div class="row justify-content-center">
                <div class="col-md-12">
                    <div class="panel panel-default" style="height: 500px !important; overflow: scroll">
                        <div class="panel-heading">
                            <div class="d-flex justify-content-between align-items-center"
                                 style="display: flex; align-items: center; justify-content: space-between">
                                <h3 class="panel-title flex-grow-1" style="display: inline">聊天界面</h3>
                                <button type="button" class="btn btn-danger">退出登录</button>
                            </div>
                        </div>
                        <div id="messages-container">
    
                        </div>
                    </div>
                    <div class="panel-footer">
                        <div class="input-group">
                            <input type="hidden" id="username" value="{{ session['username'] }}">
                            <input type="text" id="content" class="form-control" placeholder="请输入消息">
                            <span class="input-group-btn">
                            <button onclick="sendMessage()" class="btn btn-primary" type="button">发送</button>
                            </span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <script>
            // 每五秒获取一次聊天记录
            setInterval(getMessages, 100);
    
            function getMessages() {
                $.ajax({
                    url: '/recv',
                    type: 'POST',
                    success: function (response) {
                        // 更新聊天页面内容
                        var messagesContainer = document.getElementById('messages-container');
                        messagesContainer.innerHTML = '';
                        response.forEach(function (message) {
                            var messageDiv = '<div class="message left-message mb-2"><div class="message-content">' + message.username + ':' + message.content + '</div></div>';
                            messagesContainer.innerHTML += messageDiv;
                        });
                    }
                });
            }
    
            function sendMessage() {
                // 获取用户名和消息内容
                var username = document.getElementById('username').value;
                var content = document.getElementById('content').value;
    
                // 发送消息到后端
                $.ajax({
                    url: '/send',
                    type: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify({'username': username, 'content': content}),
                    success: function (response) {
                        // 清空输入框
                        document.getElementById('content').value = '';
                    }
                });
            }
        </script>
    {% endblock %}
    声明:本文由 (博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。

    还没有人喜爱这篇文章呢

    发一条! 发一条!
    博客logo 博客 | 棋の小站 记录学习,心得,状态,生活。
    ICP 冀ICP备2023007665号 ICP 冀公网安备 13030202003453号

    🕛

    本站已运行 221 天 14 小时 48 分

    👁️

    今日访问量:334 昨日访问量:2564

    🌳

    建站:Typecho 主题:MyLife
    博客 | 棋の小站. © 2023 ~ 2023.
    网站logo

    博客 | 棋の小站 记录学习,心得,状态,生活。
     
     
     
     
    壁纸