首页 > 解决方案 > django中的切片与查询集

问题描述

这一切都始于我试图将切片应用于查询集以限制它。据我了解文档应该将结果限制为 10 个条目:

def get_queryset(self, *args, **kwargs):

    qs = Message.objects.all()  
    qs = qs.filter(Target_id=self.dialog)[:10]    # here the limit
    qs = qs.annotate(sender_id=Max('Sender__id')) 
    return qs

但实际上在模板中,请求将所有记录返回给我,但仅将注释应用于前 10 条。我不知道为什么。

我认为整个原因是注释。

然后我删除最后一行(带注释)。但是,我在模板中获得了所有记录而不是 10 条。这与我没有制作切片的结果相同。

在我的模板中,我没有做任何不寻常的事情:对我的查询集的迭代:

{% for message in messages %}
  {{message}}
{% endfor %}

这很奇怪:如果我考虑len(qs)一下,我会得到 10!但在模板中我得到 300!它不适合我的头脑。

我还尝试在模板中应用切片而不是我的视图:

{% for message in messages|slice:":10" %}

但一切都没有改变。

我的模板中收到了所有消息,而不是 10 条。这怎么可能?

PS:数据库类型是sqlite。

标签: pythondjangodjango-queryset

解决方案


记载,切片后进一步修改查询集是不可取的

另请注意,即使对未评估的切片QuerySet返回另一个未评估QuerySet,也不允许对其进行进一步修改(例如,添加更多过滤器或修改排序),因为这不能很好地转化为 SQL,而且它也没有明确的含义。

您应该更改顺序,例如:

def get_queryset(self, *args, **kwargs):
    return Message.objects.filter(Target_id=self.dialog).annotate(
        sender_id=Max('Sender__id')
    )[:10]

所以你首先 .filter(..)/ .annotate(..),然后你切片。


推荐阅读