由于延迟加载,与Pony ORM一起使用DatabaseSessionIsOver吗? [英] DatabaseSessionIsOver with Pony ORM due to lazy loading?
问题描述
我将Pony ORM用于烧瓶溶液,遇到了以下问题.
I am using Pony ORM for a flask solution and I've come across the following.
请考虑以下内容:
@db_session
def get_orders_of_the_week(self, user, date):
q = select(o for o in Order for s in o.supplier if o.user == user)
q2 = q.filter(lambda o: o.date >= date and o.date <= date+timedelta(days=7))
res = q2[:]
#for r in res:
# print r.supplier.name
return res
当我需要Jinja2中的结果时-看起来像这样
When I need the result in Jinja2 -- which is looks like this
{% for order in res %}
Supplier: {{ order.supplier.name }}
{% endfor %}
我得到一个
DatabaseSessionIsOver: Cannot load attribute Supplier[3].name: the database session is over
如果我取消注释for r in res
部分,则可以正常工作.我怀疑有些延迟加载无法用res = q2[:]
加载.
我是完全遗漏了一点还是这里发生了什么?
If I uncomment the for r in res
part, it works fine. I suspect there is some sort of lazy loading that doesn't get loaded with res = q2[:]
.
Am I completely missing a point or what's going on here?
推荐答案
之所以会发生这种情况,是因为您试图访问未加载的相关对象,并且试图在数据库会话之外访问该对象(该函数用db_session
装饰),Pony会引发此异常.
This happens because you're trying to access the related object which was not loaded and since you're trying to access it outside of the database session (the function decorated with the db_session
), Pony raises this exception.
推荐的方法是在放置Flask的app.route
装饰器的同一位置,在顶层使用db_session
装饰器:
The recommended approach is to use the db_session
decorator at the top level, at the same place where you put the Flask's app.route
decorator:
@app.route('/index')
@db_session
def index():
....
return render_template(...)
这样,所有对数据库的调用都将被数据库会话包装,该会话将在生成网页后完成.
This way all calls to the database will be wrapped with the database session, which will be finished after a web page is generated.
如果出于某种原因想要将数据库会话范围缩小到单个函数,则需要在用db_session
装饰的函数中迭代返回的对象,并访问所有必需的相关对象. Pony将使用最有效的方式从数据库加载相关对象,从而避免了N + 1查询问题.这样,当与数据库的连接仍处于活动状态时,Pony将提取db_session
范围内的所有必需对象.
If there is a reason that you want to narrow the database session to a single function, then you need to iterate the returning objects inside the function decorated with the db_session
and access all the necessary related objects. Pony will use the most effective way for loading the related objects from the database, avoiding the N+1 Query problem. This way Pony will extract all the necessary objects within the db_session
scope, while the connection to the database is still active.
-更新:
现在,要加载相关对象,您应该遍历查询结果并调用相关对象属性:
Right now, for loading the related objects, you should iterate over the query result and call the related object attribute:
for r in res:
r.supplier.name
它与您示例中的代码相似,我只是删除了print
语句.当您触摸" r.supplier.name
属性时,Pony会加载相关的supplier
对象的所有非惰性属性.如果需要加载惰性属性,则需要分别触摸它们.
It is similar to the code in your example, I just removed the print
statement. When you 'touch' the r.supplier.name
attribute, Pony loads all non-lazy attributes of the related supplier
object. If you need to load lazy attributes, you need to touch each of them separately.
似乎我们需要引入一种方法来指定在查询执行期间应加载哪些相关对象.我们将在将来的版本之一中添加此功能.
Seems that we need to introduce a way to specify what related objects should be loaded during the query execution. We will add this feature in one of the future releases.
这篇关于由于延迟加载,与Pony ORM一起使用DatabaseSessionIsOver吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!