javascript - Flask:如何根据聊天室添加聊天记录?
问题描述
我正在尝试在我的烧瓶应用程序中实现一项功能,用户可以在其中创建或加入房间并相互聊天。我已经建立了用户可以聊天、创建和加入房间的部分,但我还想根据他们所在的房间添加聊天历史记录,这样当新用户加入或离开和加入时,他们可以看到所有以前的特定消息到他们所在的聊天室。消息在发送时也会保存。我现在遇到的问题是我需要显示消息并将它们保留在特定于房间的位置。我知道这需要 AJAX 和 Javascript,但我对它们都是新手。如果有人可以帮助我理解并提供以下代码来解决此问题,将不胜感激。代码如下,提前致谢!
主文件
from flask import Flask, request, session, render_template, redirect, url_for, flash, get_flashed_messages, jsonify
from flask.globals import current_app
from flask_login import LoginManager, login_user, login_required, logout_user, current_user, UserMixin, AnonymousUserMixin
from datetime import timedelta, datetime
from werkzeug.security import generate_password_hash, check_password_hash
import sqlite3
from os import error, path
from flask_sqlalchemy import SQLAlchemy
import random
from flask_socketio import SocketIO, join_room, leave_room, emit
from flask_session import Session
app = Flask(__name__)
DB_NAME = "spark.db"
app.config["SECRET_KEY"] = "1986319249872139865432"
app.config['SQLALCHEMY_DATABASE_URI'] = f"sqlite:///{DB_NAME}"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config['SESSION_TYPE'] = 'filesystem'
Session(app)
socketio = SocketIO(app, manage_session=False)
db = SQLAlchemy(app)
db.init_app(app)
def create_database(app):
if not path.exists(DB_NAME):
db.create_all(app=app)
print("Created Database!")
class Tutor(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
tremail = db.Column(db.String(10000))
trusername = db.Column(db.String(1200))
subjects = db.Column(db.String(1200))
session_length = db.Column(db.String(1200))
class Content(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
room_id = db.Column(db.Integer)
message = db.Column(db.String(5000))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
username = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
tutors = db.relationship('Tutor')
create_database(app)
login_manager = LoginManager()
login_manager.login_view = 'login'
login_manager.init_app(app)
@login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
@app.route("/")
@login_required
def home():
return render_template("index.html")
@app.route("/login", methods=["GET", 'POST'])
def login():
if request.method == "POST":
email = request.form.get('email')
password = request.form.get('password')
user = User.query.filter_by(email=email).first()
if user:
if check_password_hash(user.password, password):
flash('Login successful!', category="success")
login_user(user, remember=True)
return redirect(url_for("home"))
else:
flash('Incorrect password! Please try again.', category="error")
else:
flash("Account does not exist. Please register to continue.", category="error")
return render_template("login.html", user=current_user)
@app.route("/register", methods=["GET", "POST"])
def register():
if request.method == 'POST':
email = request.form.get('email')
username = request.form.get('username')
password1 = request.form.get('password1')
password2 = request.form.get('password2')
user = User.query.filter_by(email=email).first()
if user:
flash("Email already exists.", category="error")
elif len(email) < 4:
flash("Email must be greater than 3 characters.", category="error")
elif len(username) < 2:
flash("Username must be greater than 1 character.", category="error")
elif password1 != password2:
flash("Passwords do not match! Please try again.", category="error")
elif len(password1) < 8:
flash("Password must be greater than 7 characters.", category="error")
else:
new_user = User(email=email, username=username, password=generate_password_hash(password1, method='sha256'))
db.session.add(new_user)
db.session.commit()
login_user(new_user, remember=True)
flash("Account successfully created!", category="success")
return redirect(url_for('home'))
return render_template("register.html", user=current_user)
@app.route("/logout")
@login_required
def logout():
logout_user()
flash("Logged out succcessfully!", category="success")
return redirect(url_for('login'))
@app.route("/selection")
@login_required
def selection():
return render_template("selection.html")
@app.route("/tutorform", methods=['GET', 'POST'])
@login_required
def tutorform():
if request.method == 'POST':
email = request.form.get('email')
tremail = request.form.get('tremail')
trusername = request.form.get('trusername')
subjects = request.form.get('subjects')
session_length = request.form.get('session_length')
new_tutor = Tutor(user_id=current_user.id, tremail=tremail, trusername=trusername, subjects=subjects, session_length=session_length)
db.session.add(new_tutor)
db.session.commit()
flash('Entry has been saved!', category='success')
return redirect(url_for("display"))
return render_template("tutorform.html", user=current_user)
@app.route("/tutoreeform", methods=['GET', 'POST'])
@login_required
def tutoreeform():
if request.method == 'POST':
flash("Tutoree Entry Successful!", category='success')
return redirect(url_for("display"))
return render_template("tutoreeform.html")
@app.route("/display")
@login_required
def display():
users = Tutor.query.all()
messages = Content.query.all()
return render_template("display.html", users=users, messages=messages)
@login_required
@app.route('/chat', methods=['GET', 'POST'])
def chat():
if(request.method=='POST'):
username = current_user.username
room = request.form['room']
#Store the data in session
session['username'] = username
session['room'] = room
return render_template('chat.html', session = session)
else:
if(current_user.username is not None):
return render_template('chat.html', session = session)
else:
return redirect(url_for('chatselection'))
class Anonymous(AnonymousUserMixin):
def __init__(self):
self.username = 'Guest'
@socketio.on('join', namespace='/chat')
@login_required
def join(message):
room = session.get('room')
join_room(room)
emit('status', {'msg': current_user.username + ' has entered the room.'}, room=room)
@socketio.on('text', namespace='/chat')
@login_required
def text(message):
room = session.get('room')
sent_message = message['msg']
emit('message', {'msg': session.get('username') + ' : ' + sent_message}, room=room)
messages = Content(room_id=room, message=sent_message)
db.session.add(messages)
db.session.commit()
@socketio.on('left', namespace='/chat')
@login_required
def left(message):
room = session.get('room')
leave_room(room)
session.clear()
emit('status', {'msg': current_user.username + ' has left the room.'}, room=room)
@app.route("/chatselection", methods=['GET', 'POST'])
def chatselection():
return render_template("chatselection.html")
if __name__ == '__main__':
db.create_all()
socketio.run(app, host="192.168.1.176", port=5000, debug=True)
base.html
<!DOCTYPE html>
<html>
<head>
<title >{% block title %}{% endblock %}</title>
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='style.css') }}">
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='bootstrap.min.css') }}">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
<!-- Bootstrap core JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!-- Plugin JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/startbootstrap-stylish-portfolio@5.0.9/js/stylish-portfolio.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
<script src="https://cdn.socket.io/3.1.3/socket.io.min.js" integrity="sha384-cPwlPLvBTa3sKAgddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket;
$(document).ready(function(){
socket = io.connect('http://' + document.domain + ':' + location.port + '/get_messages/<room_id>');
socket.on('connect', function() {
socket.emit('join', {});
});
socket.on('status', function(data) {
$('#chat').val($('#chat').val() + '<' + data.msg + '>\n');
$('#chat').scrollTop($('#chat')[0].scrollHeight);
});
socket.on('message', function(data) {
$('#chat').val($('#chat').val() + data.msg + '\n');
$('#chat').scrollTop($('#chat')[0].scrollHeight);
});
$('#send').click(function(e) {
text = $('#text').val();
$('#text').val('');
socket.emit('text', {msg: text});
});
});
function leave_room() {
socket.emit('left', {}, function() {
socket.disconnect();
// go back to the login page
window.location.href = "{{ url_for('display') }}";
});
}
</script>
</head>
<body style="background-image: url(https://i.pinimg.com/originals/55/74/54/557454f9d762c6b6c9efdaec66b4dbb9.jpg)">
<nav class="navbar navbar-expand-lg navbar-dark" style="background-color: #549bf773;">
<a class="navbar-brand" href="/">
<img src="{{url_for('static', filename='logo.jpg')}}" alt="" width="40">
</a>
<a class="navbar-brand" href="/" style="color: rgb(22, 9, 3);"><i><b style="font-family: fantasy; font-size: larger;">SparkWIT</b></i></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
{% if current_user.is_authenticated %}
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/" style="color: rgb(37, 20, 13);"><b><i>Home</i></b> <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item active">
<a class="nav-link" href="/selection" style="color: rgb(37, 20, 13);"><b><i>Selection</i></b> <span class="sr-only">(current)</span></a>
</li>
</ul>
<a class="nav-link" href="/logout"><button type="button" class="btn btn-outline-danger" style="color: rgb(0, 0, 0);"><b>Logout</b></button></a>
{% else %}
<a class="nav-link" href="/login"><button type="button" class="btn btn-outline-light"><b>Login</b></button></a>
<a class="nav-link" href="/register"><button type="button" class="btn btn-outline-warning"><b>Register</b></button></a>
{% endif %}
</div>
</nav>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
{% if category == "error" %}
<div class="alert alert-danger alter-dismissable fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
{% if category == "success" %}
<div class="alert alert-success alter-dismissable fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
<div class="container">
{% block content %}{% endblock %}
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
聊天.html
{% extends "base.html" %}
{% block title %}SparkWIT | | Chat{% endblock %}
{% block content %}
<div class="chatwindow">
<center><h2 style="color: beige;">SparkWIT Babbles!</h2></center>
<center><h3 style="color: beige;">Room : {{session['room']}}</h3></center><br>
<center><textarea id="chat" cols="90" rows="12" placeholder="No messages yet. Start one..."></textarea><br /><br /></center>
<div>
<center><div class="buttonIn">
<input type="text" id="text" name="text" size="75" placeholder="Enter your message here" />
<button type="button" id="send" class="btn btn-success">SEND</button>
<br>
<br>
</div></center>
<center><button type="button" class="btn btn-danger" onclick=leave_room()>Leave this Chat</button></center>
</div>
{% endblock %}
聊天选择.html
{% extends "base.html" %}
{% block title %}SparkWIT | | Chat Selection{% endblock %}
{% block content %}
<center><h1 class="h2 mb-3 font-weight-normal" style="color: beige;">Choose or Join a room!</h1><br><br></center>
<br>
<hr>
<form class="form-signin" action="{{url_for('chat')}}" method="POST">
<input type="number" id="room" name="room" class="form-control" placeholder="Room Code (Please enter a number)" required><br>
<button class="btn btn-lg btn-dark btn-block" value="submit">Join Room</button>
</form>
<br>
<br>
<form class="form-signin" action="{{url_for('chat')}}" method="POST">
<input type="number" id="room" name="room" class="form-control" placeholder="Room Code (Please enter a number)" required><br>
<button class="btn btn-lg btn-secondary btn-block" value="submit">Create Room</button>
</form>
<br>
{% endblock %}
解决方案
推荐阅读
- intrinsics - 使用 AVX 从三个向量中随机播放元素
- javascript - Three.js如何制作彩色圆形粒子?
- swift - XCode 12: 'SessionDelegate' 在不同的模块中有不同的定义
- sql - MS SQL 合并同一张表的水平选择结果
- javascript - 未定义变量:@foreach 中的产品
- c# - 如何计算“如果”dataGridView 列不为空
- ruby-on-rails - Ruby delay_job gem如何停止进程
- r - 魔术包中的问题向图像添加边距然后注释文本
- python - 是否可以编写一个以特定格式返回多个值的函数?
- javascript - 使用 puppeteer 获取完整的网页源代码 html - 但总是缺少某些部分