Я создаю приложение для чата basi c для проекта cs502.
У меня есть dict, в котором хранятся все мои сообщения с именем пользователя, временем и сообщением, а значения содержимого сообщения находятся в список.
Прямо сейчас я использую сеансы для хранения каждого сообщения в отдельном канале, но когда я отправляю сообщение в чат, я получаю трассировку ...
Exception in thread Thread-5:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/socketio/server.py", line 682, in _handle_event_internal
r = server._trigger_event(data[0], namespace, sid, *data[1:])
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/socketio/server.py", line 711, in _trigger_event
return self.handlers[namespace][event](*args)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/flask_socketio/__init__.py", line 282, in _handler
return self._handle_event(handler, message, namespace, sid,
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/flask_socketio/__init__.py", line 713, in _handle_event
ret = handler(*args)
File "/Users/aparep7474/Desktop/project2/application.py", line 103, in post
if len(messages_created[session['current_channel']]) > 100:
KeyError: 'Hello'
Когда пользователь нажимает кнопку публикации, он принимает значение поля ввода, а затем генерирует функцию отправки сообщения. Затем его получает мое приложение flask, где оно добавляет информацию к dict и выдает сообщение, которое будет динамически показано пользователю.
Мой Flask код:
Большая часть важный код находится в конце
import os, requests
from flask import Flask, session, redirect, render_template, request, jsonify
from flask_socketio import SocketIO, emit
from helpers import login_required
app = Flask(__name__)
app.config["SECRET_KEY"] = "4301"
socketio = SocketIO(app, async_mode='eventlet')
users_online = []
channels_created = []
messages_created = {}
@app.route("/")
@login_required
def index():
if session.get("current_channel") is None:
return redirect("/create_channel")
else:
return redirect("/channels/" + session.get("current_channel"))
@app.route("/log_in", methods=['GET','POST'])
def log_in():
username = request.form.get("username")
if request.method == "POST":
if len(username) == 0:
return render_template("error.html", message="username can't be empty.")
if username in users_online:
return render_template("error.html", message="that username already exists.")
users_online.append(username)
session['username'] = username
session.permanent = True
return redirect("/create_channel")
else:
return render_template("log_in.html")
@app.route("/log_out", methods=['GET','POST'])
def log_out():
try:
users_online.remove(session['username'])
except ValueError:
pass
session.clear()
return redirect("/")
@app.route("/create_channel", methods=['GET','POST'])
@login_required
def create_channel():
session.pop("current_channel", None)
new_channel = request.form.get("channel")
if request.method == "POST":
if new_channel in channels_created:
return render_template("error.html", message="that channel already exists.")
channels_created.append(new_channel)
return redirect("/channels/" + new_channel)
else:
return render_template("create_channel.html", channels=channels_created)
@app.route("/channels/<channel>", methods=['GET','POST'])
@login_required
def channel_name(channel):
session['current_channel'] = channel
session.permanent = True
return render_template("channel.html", channels=channels_created)
@socketio.on("submit post")
def post(data):
if len(messages_created[session['current_channel']]) > 100:
messages_created[session['current_channel']].pop(0)
messages_created[session['current_channel']].append([session.get("username"), data["message"], datetime.now().strftime("%H:%M")])
message = data["message"]
time = datetime.now().strftime("%H:%M")
emit("announce post", {"message": message, "time": time, "username": session.get("username")}, room=room, broadcast=True)
if __name__ == '__main__':
socketio.run(app, debug=True)
Мой HTML Код:
{% extends "layout.html" %}
{% block title %}
{{ session.current_channel }}
{% endblock %}
{% block head %}
<style>
#box {
box-sizing: border-box;
border-radius: 5px;
width: 100%;
padding: 10px;
border: 1px solid gray;
margin: 0;
}
</style>
<script src="{{url_for('static', filename='channel.js')}}"></script>
{% endblock %}
{% block content %}
<h1 class="text-center">{{ session.current_channel }}</h1>
<body>
<div id="box">
{% if messages_created %}
{% for message in messages_created %}
<ul>
<li><strong> {{ message[0] }} </strong> : {{ message[1] }} <small class="float-right"> {{ message[2] }} </small></li>
</ul>
{% endfor %}
{% endif %}
<ul id="posts">
</ul>
</div>
<hr>
<form id="form">
<input id="message" autofocus autocomplete="off" placeholder="Enter Your Post Here" style="height: 40px;width: 800px;" class="mt-3">
<button id="button" class="btn btn-secondary">Post</button>
</form>
</body>
{% endblock %}
Макет. html просто содержит панель навигации, которая просто содержит раскрывающийся список с каналами и кнопка выхода.
Наконец мой JS Код:
document.addEventListener('DOMContentLoaded', () => {
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
socket.on('connect', () => {
document.querySelector('#form').onsubmit = () => {
const message = document.querySelector('#message').value;
socket.emit('submit post', {'message': message});
document.querySelector("#message").value = '';
return false;
};
});
socket.on('announce post', data => {
console.log('received');
const li = document.createElement('li');
li.innerHTML = `<strong> ${data.username} </strong> : ${data.message} <small class="float-right"> ${data.time} </small>`;
document.querySelector('#posts').append(li);
});
});