使用SQLAlchemy更新数据无法commit,报NoneType无rating属性错误
问题原因分析
- 核心原因是POST请求时视图函数未获取到有效的电影ID,导致
Movie.query.filter_by(id=movie_id).first()返回None,后续对None访问rating属性触发报错,事务直接中断所以没有修改数据库。 - 具体触发逻辑:你在GET请求进入编辑页时,是通过URL参数
id获取要编辑的电影ID,但前端提交表单时,form标签的action没有携带该ID参数,导致POST请求到达视图函数时,request.args.get('id')返回空值,无法查询到对应电影记录。 - 额外隐患:当前代码没有做查询结果非空判断,只要ID无效就会直接抛出属性错误,缺少异常兜底逻辑。
解决步骤
方法1:在表单提交路径中携带ID参数(改动最小)
- 修改编辑页视图函数,添加异常兜底并将电影ID传递到前端:
from flask import abort @app.route('/edit', methods=['GET','POST']) def edit_movie(): movie_id = request.args.get('id') # ID不存在直接返回404,避免后续逻辑出错 if not movie_id: abort(404) form = Edit_Form() print(movie_id) if request.method == 'POST': # 改用get_or_404,查不到对应电影直接返回404,不会触发属性错误 movie_update = Movie.query.get_or_404(movie_id) movie_update.rating = form.rating.data movie_update.review = form.review.data db.session.commit() return redirect(url_for('home')) # 把movie_id传递给前端模板 return render_template('edit.html', form=form, movie_id=movie_id)
- 修改前端form的action属性,提交时携带ID参数:
<form action="{{ url_for('edit_movie', id=movie_id) }}" method="POST"> {{ form.csrf_token }} <p>请输入新的评分</p> {{ form.rating }} <p>请填写你的影评 </p> {{ form.review }} {{ form.submit }} </form>
方法2:使用表单隐藏字段传递ID(更规范)
- 在
Edit_Form表单类中新增ID隐藏字段:
from wtforms import HiddenField class Edit_Form(FlaskForm): # 原有rating、review、submit等字段保持不变 id = HiddenField('id')
- 修改视图函数,直接通过表单传递ID:
from flask import abort @app.route('/edit', methods=['GET','POST']) def edit_movie(): movie_id = request.args.get('id') if not movie_id: abort(404) # 实例化表单时直接给id隐藏字段赋值 form = Edit_Form(id=movie_id) if request.method == 'POST': # POST请求时从表单字段获取ID,不依赖URL参数 movie_update = Movie.query.get_or_404(form.id.data) movie_update.rating = form.rating.data movie_update.review = form.review.data db.session.commit() return redirect(url_for('home')) return render_template('edit.html', form=form)
- 前端代码无需额外改动,表单会自动渲染隐藏的ID字段,提交时自动携带参数。
内容的提问来源于stack exchange,提问作者יבגני ברשדסקי
相关产品推荐
相关产品推荐

