如何在烧瓶页面请求之间保持查询?

时间:2014-08-22 17:04:32

标签: flask sqlalchemy flask-sqlalchemy

我需要在多个页面请求上运行相同的确切查询。 第一页呈现项目,第二页将项目导出为ex​​cel。

直接在会话上存储查询失败,因为BaseQuery不是JSON可序列化的:

session['previous_query'] = SomeModel.query

下一个选项是将查询存储为字符串:

session['previous_query'] = str(SomeModel.query)

这有效但我现在需要运行session.execute:

db.session.execute(session['previous_query'])

这并没有给我ORM对象,而是没有关系的简单dicts。

最后我只能存储id,但这需要我多次在两端运行查询,并且不会保留我需要的顺序。

有什么建议吗?

1 个答案:

答案 0 :(得分:4)

您可以使用SQLAlchemy Serializer扩展序列化查询:

from sqlalchemy.ext import serializer

session['previous_query'] = serializer.dumps(SomeModel.query, -1)

然后使用以下命令重新构建查询:

query = serializer.loads(session['previous_query'], db.metadata, db.session)
objects = query.all()

其中db是您的Flask-SQLAlchemy集成对象。​​

在幕后,它使用pickle模块,但酸洗已经过定制,更加紧凑,省略了会话和引擎参考;使用serializer.loads()加载序列化数据时会再次加载这些数据。

为了在Python 2上工作,您需要设置协议版本(第二个参数为serializer.dumps()),因为seralization不能使用默认协议版本0.选择版本1或2而不是,或使用-1选择Python安装支持的最高版本。

因为它使用泡菜,所以要小心从不受信任的来源加载泡菜; Flask会话是防篡改的,因为它是加密签名的,但如果攻击者能够获得您的服务器端密码,那么攻击者可以通过向您发送精心设计的serializer.loads()的pickle来接管您的流程。