由于延迟加载,与Pony ORM一起使用DatabaseSessionIsOver吗? [英] DatabaseSessionIsOver with Pony ORM due to lazy loading?

查看:127
本文介绍了由于延迟加载,与Pony ORM一起使用DatabaseSessionIsOver吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆