flask-wtf 使用wtform构造器编辑模型:预填充表单
我正在阅读《Flask Web Development》这本书,遇到了以下内容:
def edit_profile():
form = EditProfileForm()
if form.validate_on_submit():
current_user.name = form.name.data
current_user.location = form.location.data
current_user.about_me = form.about_me.data
db.session.add(user)
flash('Your profile has been updated.')
return redirect(url_for('.user', username=current_user.username))
form.name.data = current_user.name
form.location.data = current_user.location
form.about_me.data = current_user.about_me
return render_template('edit_profile.html', form=form)
简单来说,当表单没有提交或者没有通过验证时,这段代码会把当前用户的数据复制过来。然后我在研究wtforms时,看到关于表单的init方法有这样的说明:
obj – If formdata is empty or not provided, this object is checked for attributes
matching form field names, which will be used for field values.
所以我想这意味着我们可以这样写(下面的例子是我自己写的):
def edit_post(post_id):
post = Post.query.get_or_404(post_id)
if current_user != post.author:
abort(403)
# Below is the line I am concerned about
form = PostForm(formdata=request.form, obj=post)
if form.validate_on_submit():
form.populate_obj(post)
db.session.commit()
return redirect(url_for('user', username=current_user.username))
return render_template('post_form.html', form=form)
我认为这应该在GET请求时从数据库模型填充表单实例,而在POST请求后从提交的数据填充。测试了一下,似乎是有效的……
现在我的问题是:这样写编辑视图是否正确?还是应该像书里说的那样,一个字段一个字段地复制?
1 个回答
1
在处理POST请求时,使用MultiDict
来加载数据是将键值对映射到你的WTForms实例的标准方法。如果你使用Flask-WTF这个扩展,它会自动为你完成这个过程,这就是这个扩展的一个好处。
如果你查看Flask-WTF的代码,会发现它继承了WTForms的SecureForm
类,并默认尝试加载Werkzeug的POST MultiDict(叫做formdata
),前提是这个数据存在。所以在你的视图中像这样加载表单:
form = PostForm(obj=post)
如果使用Flask-WTF,这样做就足够了,还能自动填充POST请求中的数据到表单字段。
书中示例中的做法当然没有错,但会产生很多不必要的代码,并且容易出错或重复——你可能会忘记在视图中提到WTForms实例中声明的某个字段。