【问题标题】:Django: prepare query but don't execute itDjango:准备查询但不执行它
【发布时间】:2026-01-20 11:35:02
【问题描述】:

我正在尝试在以下循环中使用 Django 进行一些有效的查询:

for division in divisions:
  playoffs = league.playoff_set.filter(division=division, double_elimination=True)

我想也许在循环之前过滤playoffs,只选择带有double_elimination=True的那些会增强它:

playoffs = league.playoff_set.filter(double_elimination=True)
for division in divisions:
  division_playoffs = playoffs.filter(division=division)

但现在我担心这会在循环中的每次运行中触发来自 playoffs 的查询,而不是过滤先前检索到的结果。

它是按预期工作还是像我担心的那样工作?我应该改用Q 来构建这些性能更好的查询吗?

【问题讨论】:

  • Django 查询集是惰性的,在您需要结果之前它们不会执行。

标签: django


【解决方案1】:

Django querysets are lazy。这意味着当您这样做时不会评估查询集

playoffs = league.playoff_set.filter(double_elimination=True)

当您在循环中再次过滤查询集时,甚至不会对其进行评估。

division_playoffs = playoffs.filter(division=division)

The queryset will only be evaluated 当您访问其内容时(无论是在视图中还是在模板中)。

playoffs = league.playoff_set.filter(double_elimination=True)
for division in divisions:
    division_playoffs = playoffs.filter(division=division)
    for playoff in division_playoffs:  # looping through queryset causes it to be evaluated
        print(playoff)

因此,您的代码的两个版本的工作方式相同。你应该选择你认为更清晰的那个。

【讨论】:

  • 所以即使我坚持原来的方法(当每个循环中的查询都是 playoffs = league.playoff_set.filter(division=division, double_elimination=True) 时)它也会一样有效吗?
  • 您可以使用 Django 调试工具栏之类的工具来查看生成的 SQL 查询。正如我所说,您的代码的两个版本都可以正常工作。
  • 您可以查看已运行的 SQL 查询,可能有助于您了解幕后发生的事情。 *.com/questions/1074212/… 如果分区数量很多,但季后赛数量不多,最好只查询league.playoff_set.filter(double_elimination=True),然后在python中对结果进行分组。例如。 *.com/questions/31071888/…