【问题标题】:Django custom QuerySet evaluationDjango 自定义 QuerySet 评估
【发布时间】:2013-11-22 21:25:04
【问题描述】:

所以QuerySets 是“懒惰的”并且只在某些情况下运行(repr、list 等)。我创建了一个自定义 QuerySet 来进行许多查询,但这些最终可能会拥有数百万个项目! 这比我想返回的要多得多

返回已评估的QuerySet 时,结果不应超过 25 个!现在我知道我可以做到以下几点:

first = example.objects.filter(...)
last = first.filter(...)
result = last[:25]
#do stuff with result

但是我将使用example 对象进行很多查询,我觉得没有必要使用result = last[:25] 行。 有没有办法指定QuerySet 的返回方式?

如果有,我该如何更改它,以便 每当评估 QuerySet它只返回 QuerySet 中的第一个 x 项目,在这种情况下,@ 987654331@

重要提示:

切片必须在评估中,因为这样我可以在没有有限结果的情况下链接查询,但是当我在评估时返回结果时,它的最大值为x

【问题讨论】:

    标签: python django customization django-queryset


    【解决方案1】:

    我不确定我是否理解您对查询集进行切片的问题。如果是额外的代码行或硬编码的数字困扰您,您可以运行

    example.objects.filter(**filters)[:x]
    

    并将 x 传递给您正在使用的任何方法。

    【讨论】:

    • 这是额外的代码行,我知道我可以使用x,我只是觉得没有必要,因为这会被调用很多次,比如数千次,我不能为每个自定义都这样做过滤,因为切片会评估它,然后您将无法链接
    • 文档说:“通常,对 QuerySet 进行切片会返回一个新的 QuerySet——它不会评估查询。”所以我想说你的答案是要走的路。
    • @möter “一般”,在某些情况下确实如此,时间非常重要,我不能冒险评估它。这也是针对 API 的,它会破坏 API
    • @möter 另外,我必须在每个查询方法的末尾放置一个切片,其中有超过 50 个,并且将继续添加许多。如果我可以让它总是返回第一个 x 结果,那将是理想的。
    • @RyanSaxe 通常这里指的是不使用“step”参数进行切片时。
    【解决方案2】:

    你可以写一个自定义的Manager

    class LimitedNumberOfResultsManager(models.Manager):
        def get_queryset(self):
            return super(LimitedNumberOfResultsManager, self).get_queryset()[:25]
    

    注意:您可能认为在此处添加切片会立即评估查询集。它不会。相反,有关查询限制的信息将保存到底层 Query 对象中,并在以后的最终评估期间使用——只要它在此期间没有被另一个切片覆盖。

    然后将管理器添加到您的模型中:

    class YourModel(models.Model):
        # ...
    
        objects = LimitedNumberOfResultsManager()
    

    在设置YourModel.objects.all() 和查询集上的其他操作后,将始终只返回最多 25 个结果。您仍然可以随时使用切片覆盖它。例如:

    这将返回最多 25 个结果:

    YourModel.objects.filter(lorem='ipsum')
    

    但这将返回最多 100 个结果:

    YourModel.objects.filter(lorem='ipsum')[:100]
    

    还有一点。覆盖默认管理器可能会使其他阅读您的代码的人感到困惑。所以我认为最好不要使用默认管理器并使用自定义管理器作为可选替代方案:

    class YourModel(models.Model):
        # ...
    
        objects = models.Manager()
        limited = LimitedNumberOfResultsManager()
    

    通过此设置,这将返回所有结果:

    YourModel.objects.all()
    

    这将只返回最多 25 个结果:

    YourModel.limited.all()
    

    根据您的具体用例,您还想查看pagination in Django

    【讨论】:

      猜你喜欢
      • 2023-04-05
      • 1970-01-01
      • 2015-08-18
      • 2017-03-29
      • 2011-04-07
      • 2014-01-28
      • 2021-06-21
      • 1970-01-01
      • 2013-07-21
      相关资源
      最近更新 更多