限制Django QuerySet的结果数量,而不使用切片

时间:2015-03-31 03:34:29

标签: python django

从Django查询集限制返回的结果集的方法是通过数组切片完成的。例如,要获得前5个人:

People.objects.all()[0:5]

或者,按名称命名:

People.objects.order_by(name)[0:5]

或按名称排序,但仅限于65岁以上的人:

People.objects.order_by(name).filter(age__gt=65)[0:5]

事实上,我可以在不具备功能的查询集中考虑的活动是有限制的。

我想知道的是,有一种方法(内部的,记录的或其他的)可以在作为限制或切片的QuerySet上调用吗? 如果没有,这样做的最佳方式是什么?


注意:

  • 是的,这可能是一个坏主意,不,我不是非常热衷于实现它,但如果有良好的理由要完成它,是否可以是
  • 是的,我知道切片是懒散地执行的,这不是我要问的。
  • This is not a duplicate of this question,正如接受的答案所说:
      

    results[:max_count]后的视图中.order_by()

1 个答案:

答案 0 :(得分:1)

查看Django Querysets, its not as blackboxy的代码似乎

def __getitem__(self, k):
    """
    Retrieves an item or slice from the set of results.
    """

    # ... trimmed ...

    if isinstance(k, slice):
        qs = self._clone()
        if k.start is not None:
            start = int(k.start)
        else:
            start = None
        if k.stop is not None:
            stop = int(k.stop)
        else:
            stop = None
        qs.query.set_limits(start, stop)
        return list(qs)[::k.step] if k.step else qs

    qs = self._clone()
    qs.query.set_limits(k, k + 1)
    return list(qs)[0]

关键是:

qs.query.set_limits(start, stop)

切片延迟的原因是它只需要startstop值并将它们传递给另一个方法。

Which corresponds to a call to the sql.Query object here:

def set_limits(self, low=None, high=None):

因此可以(虽然可能不推荐)切片查询集,如下所示:

people = People.objects.order_by(name).filter(age__gt=65) # unevaluated
people.query.set_limits(start, stop)  # still unevaluated
for person in people:  # now its evaluated
    person.do_the_thing()