Flask登录表单SQLAlchemy报错:如何绑定列与数据表?
Flask登录功能开发:数据表创建问题
我正在用Flask搭建带登录功能的网页,目前开发到登录表单环节,Flask代码和HTML页面代码如下,运行时出现no such table: users错误,想知道怎么把定义的模型和数据表绑定。知道db.create_all()可以创建表,但教程说不用db.Table,有点困惑,求解决。
Flask代码
from flask import Flask,render_template,request from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.app_context().push() app.secret_key = 'hello' app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///users.sqlite3' app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False db = SQLAlchemy(app) counter = 1 class users(db.Model): id = db.Column('id',db.Integer,primary_key=True) name = db.Column('name',db.String(100)) password = db.Column('password',db.String(100)) role = db.Column('role',db.String(100)) def __init__(self,id:int,name:str,password:str,role:str): self.name = name self.password = password self.id = counter self.role = role usr = users(0,'Samantha (Root) Groves','password','Grey-hat') db.session.add(usr) @app.route('/',methods=['POST','GET']) def frontPage(): if request.method=='POST': user = request.form['Username'] password = request.form['Password'] found_user = users.query.filter_by(name=user,password=password).first() #if found_user: #return 'Hello',found_user['name'] return "Hi" else: return render_template('mywebsite.html')
HTML页面代码
<html> <style> button { font-family: Verdana, Geneva, Tahoma, sans-serif; font-size: medium; color: black; background-color: aliceblue; border-style: hidden; shape-outside: border-box; cursor: default; height: 36px; width: 144px; border-radius: 9px; top: 500px; left: 680px; position: absolute; } button:hover { background-color: orangered; } </style> <head> <title>Sign in/Sign up</title> </head> <body background="backColorWebsite.png"> <form action="#" method="post"> <label id="UsernameLabel" style="font-family: Verdana, Geneva, Tahoma, sans-serif; background-color: aliceblue;position:absolute; top: 250px;left:600px; width: 144px; height: 18px; border-radius:9px; text-align: center; font-size: medium; ">Username:</label> <input type="text" name="Username" style="font-family:Verdana, Geneva, Tahoma, sans-serif; background-color: aliceblue; position: absolute; top:250px;left:760px; width:144px; height:27px; border-radius: 9px;" maxlength="10"></input> <label id="PasswordLabel" style="font-family: Verdana, Geneva, Tahoma, sans-serif; background-color: aliceblue;position:absolute; top: 350px;left:600px; width: 144px; height: 18px; border-radius:9px; text-align: center; font-size: medium;">Password:</label> <input type="password" name="Password" style="font-family:Verdana, Geneva, Tahoma, sans-serif; background-color: aliceblue; position: absolute; top:350px;left:760px; width:144px; height:27px; border-radius: 9px;"></input> <button value="submit">Sign in</button> </form> </body> </html>
运行错误信息
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users [SQL: SELECT users.id AS users_id, users.name AS users_name, users.password AS users_password, users.role AS users_role FROM users WHERE users.name = ? AND users.password = ? LIMIT ? OFFSET ?] [parameters: ('', '', 1, 0)] 127.0.0.1 - - [17/Nov/2023 01:36:40] "POST / HTTP/1.1" 500 -
解决方案
问题根源
你定义了users模型,但没有触发数据表的创建操作,所以查询时数据库里根本不存在这张表。教程说不用db.Table是对的——因为你用的是声明式模型(继承db.Model),ORM会自动根据模型类生成表结构,不需要手动用db.Table定义,但必须调用db.create_all()来实际创建表。
具体修复步骤
- 添加表创建逻辑
在模型类定义后,调用db.create_all()创建所有模型对应的表,同时要在Flask应用上下文环境中执行这个操作。 - 修正模型的ID赋值逻辑
已经把id设为primary_key=True,SQLAlchemy会自动生成自增ID,不需要手动用counter赋值,否则会导致重启程序后ID重复。 - 避免重复添加初始用户
直接在全局代码添加用户会导致每次启动程序都重复添加,要先查询是否存在该用户再执行添加操作。 - 修正表单提交地址
HTML表单的action="#"改为action="/",确保提交到正确的路由。
修正后的Flask代码
from flask import Flask, render_template, request from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.secret_key = 'hello' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.sqlite3' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) class users(db.Model): id = db.Column('id', db.Integer, primary_key=True) name = db.Column('name', db.String(100), unique=True) # 用户名设为唯一,避免重复 password = db.Column('password', db.String(100)) role = db.Column('role', db.String(100)) def __init__(self, name: str, password: str, role: str): self.name = name self.password = password self.role = role # 在应用上下文里创建表并添加初始用户 with app.app_context(): db.create_all() # 检查初始用户是否存在,避免重复添加 if not users.query.filter_by(name='Samantha (Root) Groves').first(): usr = users('Samantha (Root) Groves', 'password', 'Grey-hat') db.session.add(usr) db.session.commit() @app.route('/', methods=['POST', 'GET']) def frontPage(): if request.method == 'POST': user = request.form['Username'] password = request.form['Password'] found_user = users.query.filter_by(name=user, password=password).first() if found_user: return f'Hello, {found_user.name}' return "用户名或密码错误" else: return render_template('mywebsite.html')
修正后的HTML代码(仅调整提交地址)
<html> <style> button { font-family: Verdana, Geneva, Tahoma, sans-serif; font-size: medium; color: black; background-color: aliceblue; border-style: hidden; shape-outside: border-box; cursor: default; height: 36px; width: 144px; border-radius: 9px; top: 500px; left: 680px; position: absolute; } button:hover { background-color: orangered; } </style> <head> <title>Sign in/Sign up</title> </head> <body background="backColorWebsite.png"> <form action="/" method="post"> <label id="UsernameLabel" style="font-family: Verdana, Geneva, Tahoma, sans-serif; background-color: aliceblue;position:absolute; top: 250px;left:600px; width: 144px; height: 18px; border-radius:9px; text-align: center; font-size: medium; ">Username:</label> <input type="text" name="Username" style="font-family:Verdana, Geneva, Tahoma, sans-serif; background-color: aliceblue; position: absolute; top:250px;left:760px; width:144px; height:27px; border-radius: 9px;" maxlength="10"></input> <label id="PasswordLabel" style="font-family: Verdana, Geneva, Tahoma, sans-serif; background-color: aliceblue;position:absolute; top: 350px;left:600px; width: 144px; height: 18px; border-radius:9px; text-align: center; font-size: medium;">Password:</label> <input type="password" name="Password" style="font-family:Verdana, Geneva, Tahoma, sans-serif; background-color: aliceblue; position: absolute; top:350px;left:760px; width:144px; height:27px; border-radius: 9px;"></input> <button type="submit">Sign in</button> </form> </body> </html>
关键说明
db.create_all()会自动扫描所有继承db.Model的类,在数据库中生成对应的数据表,这就是教程说不用db.Table的原因——声明式模型已经帮你封装了表结构定义。- 必须用
app.app_context()包裹数据库操作,确保在Flask的应用上下文环境中执行,避免上下文错误。 - 初始用户添加前先查询是否存在,防止每次启动程序都重复添加相同用户,导致主键冲突。
内容的提问来源于stack exchange,提问作者Root
相关产品推荐
相关产品推荐

