视图或模板中的查询集

Queryset in view or in template

我正在尝试加速我的代码。在开发中,一切 运行 都非常顺利,但是当我将其投入生产并开始向数据库中添加更多深度数据时,我意识到它 运行 非常慢。

我在 django-toolbar 上注意到它有 运行 成千上万的查询,而它应该只有 10-20 个。我想知道这是否可能是因为我有很多内容被传送的方式。

例如,我的代码如下所示:

{% if user.profile.is_admin %}
   ...
{% endif %}

{% for stuff in user.profile.get_somestuff %}
   ...
   {{ stuff.info }}
   {{ stuff.other_info }}
   ...
{% endfor %}

是否每一个都执行一个新的查询?

我是否应该 运行 在视图中对 get_somestuff 的查询,通过上下文传递它?我是从性能角度问的。

如果 profile.get_somestuff 是一个昂贵的操作并且您在模板中多次调用它,是的,您应该在视图中调用一次并通过 context 将结果传递给模板。

def view(request):
    ...
    stuff = request.user.profile.get_somestuff()
    return render(request, 'page.html', {'stuff': stuff})

或者,您可以使用 {% with %} 标记创建一个在其自身上下文中包含值的范围:

{% with stuff=user.profile.get_somestuff %}
   ...
   {{ stuff.info }}
   {{ stuff.other_info }}
   ... do some other things with stuff
{% endwith %}

就我个人而言,我会选择第一个选项,因为在 django.db.connection.queries 的帮助下,监控您在视图中进行的数据库查询相对容易一些。确保尽可能避免发送模板查询集、惰性表达式等。

顺便说一句,请注意 DEBUG 必须设置为 True 才能使 connection.queries 生效。

如果 stuff.info 或 stuff.other_info 是其他模型的外键,那么是的,每次你点击其中的每一个以获得新的东西 obj 你可能会做另一个 select 查询每一个。

select_related 可能会对您有所帮助。它将有效地加入您在 sql 查询中预先指定的 fk 字段上的相关表。 sql 查询将比您现在 运行 的查询更复杂,但数量要少得多。