我正在使用Flask和Flask-SQLAlchemy构建应用程序。
在应用程序中,我使用以SQLAlchemy声明性语言编写的数据库模型,假设我有一个名为 Server 的表。 应用程序通过设计选择,要求用户-via WTForms-在不同页面(视图)之间设置Server表的字段值,并且我需要将实例保存到最后的观点。
我的问题是:我有2个'循环'视图,并希望直接在数据库会话中存储在第一个视图中创建的对象的实例,以便能够在第二个视图中查询会话并仅在最后一个视图(循环结束)中提交结果,就像伪代码一样(非常简化,在这种形式下没有意义但是是解释这个概念):
def first_view():
form = FormOne() #prompt the first form
if form.validate_on_submit():
#form validate, i create the instance in SQLalchemy
server = Server() #Database Model
server.hostname = form.hostname.data
loop_count = form.repetition.data
session['loop'] = loop_count
db.session.add(server) #adding the object to the session
#but i'm not committing the session in fact the next view needs to know about this new object and a third view needs to commit based on the user input
return redirect(url_for('second_view'))
return render_template("first_view.html", form=form)
def second_view():
form = FormTwo() #prompt the second form
if form.validate_on_submit():
hostname_to_search = form.hostname.data #i get some other input
#i use the input to query the session (here different server instace can appear, depends on the user input of the first view)
rslt= db.session.query(Server).filter(Server.hostname==hostname_to_search ).all()
#the session is empty and doesn't contain the instance created in the previous view... <-- :(
if session['loop'] <= 0 :
#end the loop
return redirect(url_for('commit_view'))
else:
loop_count = session.pop('loop',1)
session['loop'] = loop_count-1
#go back to the first page to add another server instance
return redirect(url_for('first_view'))
return render_template("first_view.html", form=form)
def commit_view():
#loop finished, now i can commit my final instances
db.session.commit() <--here i save the data, db.session is empty
return 'DONE!'
但是看到Flask-SQLAlchemy中的会话请求的本地,因此看起来在视图和另一个视图之间db.session 被重置/为空。
我想到的第一个解决方案就是将服务器对象值存储在flask.session
中(以json格式),但这意味着每次我需要jsonify并解析flask.session来构建每个视图中的对象:我不能使用数据库的查询功能,但是例如我必须手动检查用户输入的主机名是否已经存在于先前创建的服务器对象中。
我的问题是:如何在不同的视图之间保持数据库会话“打开”是可能的(如果有可能和良好做法):
也许我正在使用错误的方法来解决问题? (当然我可以做一个页面,但实际案例要复杂得多,需要在不同的页面之间进行构建)