SoFunction
Updated on 2024-10-28

Implementing a framework for building an online chat room from scratch based on Python

Today from scratch to do an online chat site, a variety of online chat tools have been a lot, why still do so a chat tool it, no other, interest ear!

Let's start today by completing the first part and building the overall framework of the chat site.

holistic technology stack

  • flask framework
  • Use of flask_login
  • jquery simple application

Build Permission Framework

Still using Flask to build the backend application, using the flask-login extension to handle the user login authentication logic.

First define the login form

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

A simple login form without too much explanation

Next define the database structure

class User(UserMixin, ):
    __tablename__ = 'users'
    id = (, primary_key=True)
    username = ((64), unique=True, index=True)
    password = ((64))

Currently, we only need a user table, a simple table with only three fields. The user password is also simply stored in plaintext, and the hash of the user password will be dealt with later.

The user login form can be defined below

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)
['SECRET_KEY'] = 'hardtohard'


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


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

Defined here, it only checks if the username exists, and if it does, it executes the login_user() function and logs in. The use of the user's password is also left for later.

load_user is a callback function that stores the user object into the browser session, and then when the login_user function is called, load_user is called to set the actual user to be logged in to the session. When the login is successful, the user will be redirected to the page corresponding to the chat function.

The chat function is simple, it just displays a web page.

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

Use the login_required decorator to ensure that the function is only accessible to logged in users.

Add some initialization functions

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


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


@('/adduser/<user>', methods=['GET', 'POST'])
def adduser(user):
    user = User(username=user, password='admin')
    (user)
    ()
    return "OK"

Added functions to initialize the database and add new users.

Building front-end pages

First process the landing page by adding the

{% extends "bootstrap/" %}
{% import "bootstrap/" 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 %}

Use the extension flask_bootstrap to quickly build pages.

Let's focus on the chat page, which uses Ajax to handle the text interaction.

First, let's look at the body page and fill in the code in the

{% extends 'bootstrap/' %}
{% import "bootstrap/" as wtf %}
{% block title %}Kung Fu Realm{%endblock %}
{% block head %}
<head>
<meta charset="utf-8">
<title>Hi Hi chat room</title>
<link rel="shortcut icon" href="{{ url_for('static',filename='chat/images/')}}" rel="external nofollow"  rel="external nofollow" >
<link rel="icon" href="{{ url_for('static',filename='chat/images/')}}" rel="external nofollow"  rel="external nofollow"  type="image/x-icon">
<link type="text/css" rel="stylesheet" href="/static/chat/css/" rel="external nofollow" >
<script type="text/javascript" src="{{ url_for('static', filename='chat/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: Chat Room 123 hahaha</h1></div></div>
    <div class="uinfo fn-clear">
    {% if current_user.is_authenticated %}
      <div class="uface"><img src="{{ url_for('static', filename='chat/images/') }}" width="40" height="40"  alt=""/></div>
    {% else %}
      <div class="uface"><img src="{{ url_for('static', filename='chat/images/')}}" width="40" height="40"  alt=""/></div>
    {% endif %}
      <div class="uname">
        fewHI<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>Logout</a></li>
            {% else %}
          <li><a href="{{ url_for('logout') }}" rel="external nofollow"  rel="external nofollow" ><i class="fontico logout"></i>log in</a></li>
            {% endif %}
        </ul>
      </div>
    </div>
  </div>
  <div class="chat_message fn-clear">
    <div class="chat_left">
      <div class="message_box" >
        <div class="msg_item fn-clear">
          <div class="uface"><img src="{{ url_for('static', filename='chat/images/')}}" width="40" height="40"  alt=""/></div>
          <div class="item_right">
            <div class="msg own"><img src="{{ url_for('static', filename='chat/images/')}}" width="400" height="400"  alt=""/></div>
            <div class="name_time">few黄鸭 </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/')}}" width="40" height="40"  alt=""/></div>
          <div class="item_right">
            <div class="msg">Welcome to Hihi Chat Room. Welcome to Hihi chat room。 </div>
            <div class="name_time">few黄鸭 </div>
          </div>
        </div>
          {% else %}
          <div class="msg_item fn-clear">
          <div class="uface"><img src="{{ url_for('static', filename='chat/images/')}}" width="40" height="40"  alt=""/></div>
          <div class="item_right">
            <div class="msg">You are not logged in,先和few黄鸭聊聊吧。 </div>
            <div class="name_time">few黄鸭 </div>
          </div>
        </div>
          {% endif %}
      </div>
      <div class="write_box">
      {% if current_user.is_authenticated %}
        <textarea  name="message" class="write_area" placeholder="Say something..."></textarea>
      {% else %}
      <textarea  name="message" class="write_area" placeholder="Say something..."></textarea>
      {% endif %}
        <input type="hidden" name="fromname"  value="You." />
        <input type="hidden" name="to_uid"  value="0">
        <div class="facebox fn-clear">
          <div class="expression"></div>
          <div class="chat_type" >group chat</div>
            {% if current_user.is_authenticated %}
          <button name="login" class="sub_but" >carry (hanging down from the hand) pay (money)</button>
            {% else %}
          <button name="logout" class="sub_but" >carry (hanging down from the hand) pay (money)</button>
            {% endif %}
        </div>
      </div>
    </div>
  </div>
</div>

The overall effect is as follows, isn't it quite girly.

When the user clicks the "Submit" button, the JS function is called.

    /* user logged in user clicks submit button to send message button */
    $('#sub_but_login').click(function(event){
        sendMessageLogin(event, fromname, to_uid, to_uname);
    });

For the sake of later expansion, non-logged-in users will be specifically distinguished, and later perhaps non-logged-in users will be allowed to visit the page as well, but will only be able to chat with the robot Duckling

    /* User not logged in clicks submit button to send message button */
    $('#sub_but').click(function(event){
        sendMessage(event, fromname, to_uid, to_uname);
    });

Look at the sendMessageLogin function again.

function sendMessageLogin(event, from_name, to_uid, to_uname){
    var msg = $("#message").val();
    var myDate = new Date();
    var myTime = ();
    var itTime = ();
    //var iTime = ();
    var htmlData =   '<div class="msg_item fn-clear">'
                   + '   <div class="uface">{% if current_user.is_authenticated %}<img src="{{ url_for('static', filename='chat/images/') }}" 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); //Delayed call
}

takes a few parameters, then appends the current session message to the HTML page and calls the real backend API function, sendToServer.

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

};

The sendToServer function calls the backend API and writes the received message back to the HTML page.

The current backend API is also relatively simple, returning user input directly to the message

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

In this way, an overall chat room framework has been built, and later we will access redis and our own trained chatbots to realize a real online chat room.

This article on the implementation of Python based on building an online chat room from scratch is introduced to this article, more related Python online chat room content, please search for my previous articles or continue to browse the following related articles I hope you will support me in the future!