【问题标题】:Limiting the number of results from a Django QuerySet, without using slice限制来自 Django QuerySet 的结果数量,而不使用切片
【发布时间】:2015-06-04 06:59:12
【问题描述】:

限制从 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]

事实上,我能想到的 only 活动在 没有 具有功能的查询集上是有限的。

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


注意事项:

  • 是的,这可能是个坏主意,不,我不太热衷于实施它,但如果有一个 好的 理由让它这样做,可能吗?
  • 是的,我知道切片是延迟执行的,这不是我要问的。
  • This is not a duplicate of this question,正如公认的答案所说:

    results[:max_count] 在视图中,在.order_by() 之后。

【问题讨论】:

  • 你想通过不使用切片来完成或避免什么?
  • 没什么。我正在查看一个 django 库的一些代码,它只能返回一个列表,而不是一个查询集,并且切片它存在一个问题,因为切片的惰性方面不相关,因为它首先将整个查询集转换为一个列表.
  • 根据documentation,切片是唯一的方法。
  • 在我看来,您必须将任何此类调用线程化到第三方库中 - 问题不在于语法,而在于在您想要它之前评估 qs。
  • @thefourtheye 因为切片是懒惰的,它实际上是在最后一刻才完成的。我在cmets之后挖了代码,看来你可以很容易地调用内部限制方法。

标签: python django


【解决方案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()

【讨论】:

  • 我仍然没有看到任何意义 - 如果您可以在查询集上调用 set_limits ,您也可以对其进行切片,以及您可以对 a 执行的操作的所有限制切片后的查询集也将在调用set_limits 后应用。如果您正在研究查询集的实现以用于研究目的,也许?
  • 这是一个非常学术的问题。我主要是好奇它是否可以做到。
  • @PeterDeGlopper 有时您想限制查询中返回的内容,但仍然能够传递可以进一步过滤或操作的查询集实例。在Cannot filter a query once a slice has been taken.中使用切片结果@
  • @Matt - 所以将使用set_limits!所有这些错误检查都是使用is_sliced 属性完成的,该属性检查相同的值set_limits 发生变异。 github.com/django/django/blob/… - set_limits 就在该代码的上方,很方便。
猜你喜欢
  • 2019-10-02
  • 1970-01-01
  • 2022-06-12
  • 2021-04-23
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多