如何在Django视图中组合2个以上的查询? [英] How to combine 2 or more querysets in a Django view?

查看:508
本文介绍了如何在Django视图中组合2个以上的查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个正在构建的Django站点的搜索,在搜索中,我正在3种不同的模型中进行搜索。要在搜索结果列表中获取分页,我想使用通用的object_list视图来显示结果。但是要做到这一点,我必须将3个查询集合到一个。

I am trying to build the search for a Django site I am building, and in the search I am searching in 3 different models. And to get pagination on the search result list I would like to use a generic object_list view to display the results. But to do that i have to merge 3 querysets into one.

我该怎么做?我试过这个:

How can i do that? I've tried this:

result_list = []            
page_list = Page.objects.filter(Q(title__icontains=cleaned_search_term) | Q(body__icontains=cleaned_search_term))
article_list = Article.objects.filter(Q(title__icontains=cleaned_search_term) | Q(body__icontains=cleaned_search_term) | Q(tags__icontains=cleaned_search_term))
post_list = Post.objects.filter(Q(title__icontains=cleaned_search_term) | Q(body__icontains=cleaned_search_term) | Q(tags__icontains=cleaned_search_term))

for x in page_list:
    result_list.append(x)
for x in article_list:
    result_list.append(x)
for x in post_list:
    result_list.append(x)

return object_list(request, queryset=result_list, template_object_name='result',
                   paginate_by=10, extra_context={'search_term': search_term},
                   template_name="search/result_list.html")

但这不是w ork当我尝试在通用视图中使用该列表时,我收到错误。该列表缺少克隆属性。

But this doesn't work I get an error when I try to use that list in the generic view. The list is missing the clone attribute.

任何人都知道如何合并三个列表, page_list article_list post_list

Anybody know how I can merge the three lists, page_list, article_list and post_list?

推荐答案

将查询器连接到列表中是最简单的方法。如果数据库无论如何都会被所有查询器打到(例如因为结果需要排序),这不会增加额外的费用。

Concatenating the querysets into a list is the simplest approach. If the database will be hit for all querysets anyway (e.g. because the result needs to be sorted), this won't add further cost.

from itertools import chain
result_list = list(chain(page_list, article_list, post_list))

使用 itertools.chain 比循环每个列表和附加元素要快一些,因为 itertools 被实现在C.它也消耗更少的内存比在连接之前将每个查询器转换为列表。

Using itertools.chain is faster than looping each list and appending elements one by one, since itertools is implemented in C. It also consumes less memory than converting each queryset into a list before concatenating.

现在可以对结果列表进行排序,例如按照日期(根据hasen j对另一个答案的评论的要求)。 sorted()函数方便地接受一个生成器并返回一个列表:

Now it's possible to sort the resulting list e.g. by date (as requested in hasen j's comment to another answer). The sorted() function conveniently accepts a generator and returns a list:

result_list = sorted(
    chain(page_list, article_list, post_list),
    key=lambda instance: instance.date_created)

如果您使用的是Python 2.4或更高版本,则可以使用 attrgetter 而不是lambda。我记得阅读更快,但是我没有看到一百万项目列表的速度差异显着。

If you're using Python 2.4 or later, you can use attrgetter instead of a lambda. I remember reading about it being faster, but I didn't see a noticeable speed difference for a million item list.

from operator import attrgetter
result_list = sorted(
    chain(page_list, article_list, post_list),
    key=attrgetter('date_created'))

这篇关于如何在Django视图中组合2个以上的查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆