为什么除非重新启动 Flask 服务器,否则我的列表不会从数据库刷新填充?



我有一个非常简单的烧瓶应用程序,它允许我注册用户名,然后在列表中显示这些名称。我可以注册,但列表将为空。如果我重新启动烧瓶服务器,则名称在页面加载时会出现。我尝试关闭/重新打开数据库,调用函数(填充用户列表(来刷新列表,并在 html 中禁用浏览器缓存无济于事。任何帮助将不胜感激!

app.py

from flask import Flask, render_template, url_for, request, render_template_string
from flask_wtf import FlaskForm
from wtforms import StringField, SelectField
from wtforms.validators import InputRequired, length
import sqlite3
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey'
conn = sqlite3.connect('users.db')
c = conn.cursor()
#create users.db if it doesn't exist
try:
c.execute("""CREATE TABLE users (
username text UNIQUE
)""")
print("users.db created with users table")
except:
print("users.db file exists")
c.execute("SELECT * FROM users")
userlist=c.fetchall()
conn.close()
#populate userlist from users.db
def populateuserlist():
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute("SELECT * FROM users")
userlist = c.fetchall()
conn.close()
return userlist
#form with drop down list for users page
class selectuserform(FlaskForm):
populateuserlist()
userlist = populateuserlist()
print("Login form populated with" + str(userlist) + ".")
currentuser = SelectField('currentuser', choices=[(user[0], user[0]) for user in userlist])
class RegisterNameForm(FlaskForm):
RegisterName = StringField('Username', validators= [InputRequired(), length(min=1, max=15)])
#define page routes
@app.route('/login', methods=['GET', 'POST'])
def login_page():
form = RegisterNameForm()
if form.validate_on_submit():
newuser=request.form.get("RegisterName")
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute("INSERT OR IGNORE INTO users VALUES (?)", (newuser,))
conn.commit()
conn.close()
form = selectuserform()
populateuserlist()
return render_template('login.html', userlist=userlist, form=form)
@app.route('/register', methods=['GET', 'POST'])
def register_page():
form = RegisterNameForm()
return render_template('register.html', form=form)
#start flask server
if __name__ == '__main__':
app.run(debug=True)

登录.html

<!<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div>
<button onclick="window.location.href = '/register'";>Register</button>
<center>
<h1>Select User</h1>
<form method="POST" ACTION="{{ url_for('login_page') }}">
{{ form.csrf_token }}
{{ form.currentuser }}
<br><br>
<input type="submit" value="Continue">
</form>
</center>
</div>
</body>
</html>

注册.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<button onclick="window.location.href = '/login'";>Go back</button>
<center>
<h1>Enter your name</h1>
<form method="POST" action="/login">
{{ form.hidden_tag() }}
{{ form.RegisterName }}
<br><br>
<input type="submit" value="Create user">
</form>
</center>
</body>
</html>

您不应该在 Web 应用程序中使用这样的全局值,它会让您对各种不稳定的行为持开放态度。此函数:

def populateuserlist():
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute("SELECT * FROM users")
userlist = c.fetchall()
conn.close()
return userlist 

对全局userlist名称不执行任何操作。为什么呢?在本地函数作用域中创建新名称。我故意跳过了global的使用,你不应该试图使用它。您可以使用以下方法轻松测试范围问题:

a = [1, 2, 3]
def something():
a = [2, 3, 4]
return a
something()
print(a)

因此,userlist(全局(仅在应用启动时评估一次。相反,您需要在视图中调用populateuserlist(应相应地重命名,因为它不会填充全局名称(。该问题也存在于您的表单中。您需要动态更新选项列表。

@app.route('/login', methods=['GET', 'POST'])
def login_page():
form = RegisterNameForm()
if form.validate_on_submit():
newuser=request.form.get("RegisterName")
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute("INSERT OR IGNORE INTO users VALUES (?)", (newuser,))
conn.commit()
conn.close()
form = selectuserform()
userlist = populateuserlist() # CHANGED HERE
form.currentuser.choices = [(user[0], user[0]) for user in userlist] # ADD THE NEW OPTIONS (IF ANY)
return render_template('login.html', userlist=userlist, form=form)

最新更新