基于Python实现从头搭建一个在线聊天室框架

目录
  • 整体技术栈
  • 搭建权限框架
  • 构建前端页面

今天从头开始做一个在线聊天网站,网上各种各样的聊天工具已经很多了,为啥还要做这么一个聊天工具呢,无他,兴趣耳!

今天先完成第一部分,搭建起聊天网站的整体框架。

整体技术栈

  • flask 框架
  • flask_login 的使用
  • jquery 简单应用

搭建权限框架

还是使用 Flask 来搭建后台应用,使用 flask-login 扩展来处理用户登陆鉴权逻辑。

首先定义登陆表单

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), ])
    password = PasswordField('Password', validators=[DataRequired()])
    remember_me = BooleanField('Keep me logged in')
    submit = SubmitField('Log in')

一个简单的登陆表单,不做过多解释

接下来定义数据库结构

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    password = db.Column(db.String(64))

当前,我们只需要一个 user 用户表,只包含三个字段的简单表。用户密码也只是简单的保存了明文,后面再处理用户密码的 hash 问题。

下面就可以定义用户登陆表单

from flask_login import LoginManager

login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_view = 'login'
app = Flask(__name__)
login_manager.init_app(app)
app.config['SECRET_KEY'] = 'hardtohard'

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user:
            login_user(user)
            return redirect(url_for('chat'))
    return render_template('login.html', form=form)

这里定义了,只检查用户名是否存在,如果存在,就执行 login_user() 函数,登陆。用户密码的使用,也留到后面再做处理。

其中 load_user,是回调函数,将获取到的 user 对象存储到浏览器的 session 中,然后在调用 login_user 函数时,就会调用 load_user 来把真正需要登陆的用户设置到 session 中。当登陆成功后,就会跳转到 chat 函数所对应的页面。

chat 函数比较简单,只是展示一个网页

@app.route('/chat', methods=['GET', 'POST'])
@login_required
def chat():
    return render_template('chat.html')

使用 login_required 装饰器,保证该函数只允许登陆的用户访问。

增加些初始化函数

@app.route('/adddb', methods=['GET', 'POST'])
def addbd():
    db.create_all()
    return "OK"

@app.route('/deldb', methods=['GET', 'POST'])
def delbd():
    db.drop_all()
    return "OK"

@app.route('/adduser/<user>', methods=['GET', 'POST'])
def adduser(user):
    user = User(username=user, password='admin')
    db.session.add(user)
    db.session.commit()
    return "OK"

增加了初始化数据库和新增用户的函数。

构建前端页面

首先处理登陆页面,在 login.html 中添加

{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/" rel="external nofollow"  rel="external nofollow" >Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/" rel="external nofollow"  rel="external nofollow" >Home</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                {% if current_user.is_authenticated %}
                <li><a href="{{ url_for('logout') }}" rel="external nofollow"  rel="external nofollow" >Logout</a></li>
                {% else %}
                <li><a href="{{ url_for('login') }}" rel="external nofollow"  rel="external nofollow" >Login</a></li>
                {% endif %}
            </ul>
        </div>
    </div>
</div> {% endblock %}

{% block content %}
<div class="container">
    <div class="page-header">
        <h1>Hello, Welcome!</h1>
    </div>
    {{ wtf.quick_form(form) }}
</div>
{% endblock %}

使用扩展库 flask_bootstrap 来快速构建页面。

下面重点来看看 chat 页面,主要使用了 Ajax 来处理文字交互。

首先来看看主体页面,在 chat.html 中填入代码

{% extends 'bootstrap/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Kung Fu Realm{%endblock %}
{% block head %}
<head>
<meta charset="utf-8">
<title>Hi Hi 聊天室</title>
<link rel="shortcut icon" href="{{ url_for('static',filename='chat/images/hihi.jpg')}}" rel="external nofollow"  rel="external nofollow" >
<link rel="icon" href="{{ url_for('static',filename='chat/images/hihi.jpg')}}" rel="external nofollow"  rel="external nofollow"  type="image/x-icon">
<link type="text/css" rel="stylesheet" href="/static/chat/css/style.css" rel="external nofollow" >
<script type="text/javascript" src="{{ url_for('static', filename='chat/js/jquery.min.js') }}"></script>
</head>
{% endblock %}
{% block content %}
<body>
<div class="chatbox">
  <div class="chat_top fn-clear">
      <div class="uinfo fn-clear"  style="float: left;"><div class="uface"><h1 style="color: #7777">ROOM: 聊天室123哈哈哈</h1></div></div>
    <div class="uinfo fn-clear">
    {% if current_user.is_authenticated %}
      <div class="uface"><img src="{{ url_for('static', filename='chat/images/hi.jpg') }}" width="40" height="40"  alt=""/></div>
    {% else %}
      <div class="uface"><img src="{{ url_for('static', filename='chat/images/hi.jpg')}}" width="40" height="40"  alt=""/></div>
    {% endif %}
      <div class="uname">
        小HI<i class="fontico down"></i>
        <ul class="managerbox">
            {% if current_user.is_authenticated %}
          <li><a href="{{ url_for('login') }}" rel="external nofollow"  rel="external nofollow" ><i class="fontico lock"></i>退出登陆</a></li>
            {% else %}
          <li><a href="{{ url_for('logout') }}" rel="external nofollow"  rel="external nofollow" ><i class="fontico logout"></i>登录</a></li>
            {% endif %}
        </ul>
      </div>
    </div>
  </div>
  <div class="chat_message fn-clear">
    <div class="chat_left">
      <div class="message_box" id="message_box">
        <div class="msg_item fn-clear">
          <div class="uface"><img src="{{ url_for('static', filename='chat/images/duck.jpg')}}" width="40" height="40"  alt=""/></div>
          <div class="item_right">
            <div class="msg own"><img src="{{ url_for('static', filename='chat/images/hihi.jpg')}}" width="400" height="400"  alt=""/></div>
            <div class="name_time">小黄鸭 </div>
          </div>
        </div>
          {% if current_user.is_authenticated %}
        <div class="msg_item fn-clear">
          <div class="uface"><img src="{{ url_for('static', filename='chat/images/duck.jpg')}}" width="40" height="40"  alt=""/></div>
          <div class="item_right">
            <div class="msg">Welcome to Hihi Chat Room. 欢迎来到 Hihi 聊天室。 </div>
            <div class="name_time">小黄鸭 </div>
          </div>
        </div>
          {% else %}
          <div class="msg_item fn-clear">
          <div class="uface"><img src="{{ url_for('static', filename='chat/images/duck.jpg')}}" width="40" height="40"  alt=""/></div>
          <div class="item_right">
            <div class="msg">您还没有登陆,先和小黄鸭聊聊吧。 </div>
            <div class="name_time">小黄鸭 </div>
          </div>
        </div>
          {% endif %}
      </div>
      <div class="write_box">
      {% if current_user.is_authenticated %}
        <textarea id="message" name="message" class="write_area" placeholder="说点啥吧..."></textarea>
      {% else %}
      <textarea id="message_not" name="message" class="write_area" placeholder="说点啥吧..."></textarea>
      {% endif %}
        <input type="hidden" name="fromname" id="fromname" value="你" />
        <input type="hidden" name="to_uid" id="to_uid" value="0">
        <div class="facebox fn-clear">
          <div class="expression"></div>
          <div class="chat_type" id="chat_type">群聊</div>
            {% if current_user.is_authenticated %}
          <button name="login" class="sub_but" id="sub_but_login">提 交</button>
            {% else %}
          <button name="logout" class="sub_but" id="sub_but">提 交</button>
            {% endif %}
        </div>
      </div>
    </div>
  </div>
</div>

整体效果如下,是不是挺少女系的。

当用户在点击“提交”按钮后,调用 JS 函数

    /*用户登陆的用户点击提交按钮发送消息按钮*/
    $('#sub_but_login').click(function(event){
        sendMessageLogin(event, fromname, to_uid, to_uname);
    });

为了后面便于扩展,将未登录的用户特别区分开来,后面也许同样允许未登陆用户访问该页面,但是只能同机器人小黄鸭聊天

    /*用户未登陆的用户点击提交按钮发送消息按钮*/
    $('#sub_but').click(function(event){
        sendMessage(event, fromname, to_uid, to_uname);
    });

再来看函数 sendMessageLogin

function sendMessageLogin(event, from_name, to_uid, to_uname){
    var msg = $("#message").val();
    var myDate = new Date();
    var myTime = myDate.toLocaleTimeString();
    var itTime = myDate.toLocaleString();
    //var iTime = myDate.toDateString();
    var htmlData =   '<div class="msg_item fn-clear">'
                   + '   <div class="uface">{% if current_user.is_authenticated %}<img src="{{ url_for('static', filename='chat/images/hi.jpg') }}" width="40" height="40"  alt=""/>{% endif %}</div>'
                   + '   <div class="item_right">'
                   + '     <div class="msg own">' + msg + '</div>'
                   + '     <div class="name_time">' + from_name + ' · ' + itTime +'</div>'
                   + '   </div>'
                   + '</div>';
    $("#message_box").append(htmlData);
    $('#message_box').scrollTop($("#message_box")[0].scrollHeight + 20);
    $("#message").val('');
    setTimeout(function(){sendToServer(from_name, msg)}, 1000); //延时调用
}

接收几个参数,然后将当前会话消息追加到 HTML 页面中,并且调用真正的后台 API 函数 sendToServer

function sendToServer(name, msg){
    var xmlhttp = new XMLHttpRequest();
    var myDate = new Date();
    //var myTime = myDate.toLocaleTimeString();
    var myTime = myDate.toLocaleString();
    xmlhttp.onreadystatechange=function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            myObj = xmlhttp.responseText;
            var htmlData2 =   '<div class="msg_item fn-clear">'
                   + '   <div class="uface"><img src="{{ url_for('static', filename='chat/images/duck.jpg')}}" width="40" height="40"  alt=""/></div>'
                   + '   <div class="item_right">'
                   + '     <div class="msg">' + myObj + '</div>'
                   + '     <div class="name_time">' + '小黄鸭' + ' · ' + myTime +'</div>'
                   + '   </div>'
                   + '</div>';
            $("#message_box").append(htmlData2);
            $('#message_box').scrollTop($("#message_box")[0].scrollHeight + 20);
        }
    }
    xmlhttp.open("GET", "/api/sendchat/" + msg, true);
    xmlhttp.send();

};

sendToServer 函数调用后台 API,并把接收到的消息回写到 HTML 页面中。

而目前的后台 API 也比较简单,直接返回用户输入的消息

@app.route('/api/sendchat/<info>', methods=['GET', 'POST'])
@login_required
def send_chat(info):
    return info

这样,一个整体的聊天室架子就搭建好了,后面我们再接入 redis 和自己训练的聊天机器人,来实现真正的在线聊天室。

到此这篇关于基于Python实现从头搭建一个在线聊天室的文章就介绍到这了,更多相关Python在线聊天室内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 利用Python打造一个多人聊天室的示例详解

    一.实验名称 建立聊天工具 二.实验目的 掌握Socket编程中流套接字的技术,实现多台电脑之间的聊天. 三.实验内容和要求 vii.掌握利用Socket进行编程的技术 viii.必须掌握多线程技术,保证双方可以同时发送 ix.建立聊天工具 x.可以和多个人同时进行聊天 xi.必须使用图形界面,显示双方的语录 四.实验环境 PC多台,操作系统Win7,win10(32位.64位) 具备软件python3.6 . 五.操作方法与实验步骤 服务端 1.调入多线程.与scoket包,用于实现多线程连接

  • Python实现网络聊天室的示例代码(支持多人聊天与私聊)

    实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时发送 iii. 建立聊天工具 iv. 可以和单人聊天 v. 可以和多个人同时进行聊天 vi. 使用图形界面,显示双方的语录 vii. 程序可以在一定程度上进行错误识别 概述 实验通过聊天室可以完成单人或多人之间的聊天通信,功能的实现主要是通过Socket通信来实现.本次实验采用客户端/服务器(C/S)架构模式,通过Python语言来编写服务器端与客户端的程序.运用多线程可完成多点对多

  • python实现简单聊天室功能 可以私聊

    本文实例为大家分享了python实现简单聊天室功能的具体代码,供大家参考,具体内容如下 公共模块 首先写一个公共类,用字典的形式对数据的收发,并且进行封装,导入struct解决了TCP的粘包问题,并在公共类中进行了异常处理 import socket,struct,json def send_dic(c,dic): dic_json=json.dumps(dic) dic_json_length=len(dic_json.encode('utf-8')) struct_dic_json_leng

  • python实现简单多人聊天室

    本文实例为大家分享了python实现多人聊天室的具体代码,供大家参考,具体内容如下 刚开始学习python,写了一个聊天室练练手. Server.py import socket,select,thread; host=socket.gethostname() port=5963 addr=(host,port) inputs=[] fd_name={} def who_in_room(w): name_list=[] for k in w: name_list.append(w[k]) ret

  • Python使用django框架实现多人在线匿名聊天的小程序

    最近看到好多设计类网站,都提供了多人在线匿名聊天的小功能,感觉很有意思,于是基于python的django框架自己写了一个,支持手动实时更名,最下方提供了完整的源码. 在线聊天地址(无需登录,开一个窗口,代表一个用户): http://zhaozhaoli.vicp.io/chatroom/happy/ 移动端聊天效果图: 网页版聊天效果图: 实现思路: 发送的消息通过ajax先写入数据库,通过ajax的循环请求,将写入数据库的消息显示到前端界面. 前端核心代码: <script> $(fun

  • 基于Python实现从头搭建一个在线聊天室框架

    目录 整体技术栈 搭建权限框架 构建前端页面 今天从头开始做一个在线聊天网站,网上各种各样的聊天工具已经很多了,为啥还要做这么一个聊天工具呢,无他,兴趣耳! 今天先完成第一部分,搭建起聊天网站的整体框架. 整体技术栈 flask 框架 flask_login 的使用 jquery 简单应用 搭建权限框架 还是使用 Flask 来搭建后台应用,使用 flask-login 扩展来处理用户登陆鉴权逻辑. 首先定义登陆表单 class LoginForm(FlaskForm):     usernam

  • 基于vue和websocket的多人在线聊天室

    最近看到一些关于websocket的东西,就决定写一个在线聊天室尝试一下.最终决定配合vue来写,采用了官方的vue脚手架vue-cli和官方的router,在本例中呢,我是用了CHAT这个对象来存储app的数据的,但后来一想,虽然项目很小,但如果用官方的vuex会更好,方便以后扩展,比如可以加上私信功能,可以在对方不在线的时候缓存发送的消息,这些都是可以的.(现在比较尴尬的就是,我把聊天室写好放到公众号号redream里,但是很少有人会同时在线,所以你会经常发现你进去的时候只有你一个人,就导致

  • AngularJS+Node.js实现在线聊天室

    不得不说,上手AngularJS比我想象得难多了,把官网提供的PhoneCat例子看完,又跑到慕课网把大漠穷秋的AngularJS实战系列看了一遍,对于基本的使用依然有很多说不清道不明的疑惑,于是决定通过做一个在线聊天室帮助理解.DEMO可以戳→chat room,代码可以戳→ChatRoom-AngularJS. 清晰图可以戳 http://files.jb51.net/file_images/article/201508/201508281040051.gif 功能 着手开发之前,首先明确一

  • 基于javascript、ajax、memcache和PHP实现的简易在线聊天室

    在线聊天室(online chatrooms)是一个共多人进行沟通交流的网络平台,随着越来越多的新技术的发明和成熟运用,在线聊天室也出现使用各种不同技术的, 这篇文章我想简单总结一下. 首先说一下前台技术,最新的当然是基于HTML5的websocket,它实现了浏览器与服务器全双工通信(full-duplex).WebSocket通信协议于2011年被IETF定为标准 RFC 6455,WebSocketAPI被W3C定为标准.在WebSocket API中,浏览器和服务器只需要做一个握手的动作

  • 基于python的itchat库实现微信聊天机器人(推荐)

    一.开始之前必须安装itchat库 pip install itchat(使用pip必须在电脑的环境变量中添加Python的路径) 或 conda install request 二.开始编程前,我们需要在图灵机器人官网注册自己的图灵机器人,来实现我们程序的智能聊天功能 1.图灵机器人官网(http://www.turingapi.com/) 2.注册登录后点击创建机器人 3.创建成功后,可以获得机器人提供的API接口(apikey) 三.代码实现 import itchat import re

  • Python 利用flask搭建一个共享服务器的步骤

    零.概述 我利用flask搭建了一个简易的共享服务器,分享给大家 一.python代码 import os import time from flask import Flask,render_template,url_for,redirect,send_from_directory # 共享文件夹的根目录 rootdir = r'C:\Users\Administrator\Downloads\zlkt'   app = Flask(__name__)   @app.route('/doc/'

  • Django使用channels + websocket打造在线聊天室

    Channels是Django团队研发的一个给Django提供websocket支持的框架,它同时支持http和websocket多种协议.使用channels可以让你的Django应用拥有实时通讯和给用户主动推送信息的功能. 演示效果如下所示: 什么是websocket? WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议.WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在 WebSocket API

  • Python实现的使用telnet登陆聊天室实例

    本文实例讲述了Python实现的使用telnet登陆聊天室.分享给大家供大家参考.具体如下: 前久在家学习Python的时候写的一个简单的聊天室,可以使用telnet来登陆. 遗憾的是现在对中文的支持很差,英文聊天倒是没什么问题了. 功能很简单的,应该没有你想象的那么强大,但是你如果有兴趣的话可以试试的. 另外,让我惊奇的是它可以在Android的平板上运行SL4A的Python解释器上运行(需要稍微改几句代码,貌似是编码的那个地方,我记不清了). 现在这个是可以在PC上跑起来的. 废话不多,直

  • vue + socket.io实现一个简易聊天室示例代码

    vue + vuex + elementUi + socket.io实现一个简易的在线聊天室,提高自己在对vue系列在项目中应用的深度.因为学会一个库或者框架容易,但要结合项目使用一个库或框架就不是那么容易了.功能虽然不多,但还是有收获.设计和实现思路较为拙劣,恳请各位道友指正. 可以达到的需求 能查看在线用户列表 能发送和接受消息 使用到的框架和库 socket.io做为实时通讯基础 vuex/vue:客户端Ui层使用 Element-ui:客户端Ui组件 类文件关系图 服务端: 客户端: 服

  • Java基于中介者模式实现多人聊天室功能示例

    本文实例讲述了Java基于中介者模式实现多人聊天室功能.分享给大家供大家参考,具体如下: 一 模式定义 中介者模式,用一个中介对象来封装一系列对象之间的交互,使各个对象中不需要显示地引用其他对象实例,从而降低各个对象之间的耦合度,并且可以独立地改变对象间的交互关系. 二 模式举例 1 模式分析 我们借用多人聊天室来说明这一模式 2 中介模式静态类图 3 代码示例 3.1中介者接口--IMediator package com.demo.mediator; import com.demo.coll

随机推荐