问题描述
我正在尝试为正在构建的Django网站构建搜索,在该搜索中,我正在3种不同的模型中进行搜索.为了在搜索结果列表上进行分页,我想使用一个通用的object_list视图来显示结果.但是要做到这一点,我必须将3个查询集合并为一个.
我该怎么做?我已经尝试过了:
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")
但这不起作用.当我尝试在通用视图中使用该列表时出现错误.该列表缺少克隆属性.
有人知道我如何合并page_list
,article_list
和post_list
这三个列表吗?
将查询集连接到列表是最简单的方法.如果仍然要为所有查询集命中数据库(例如,因为需要对结果进行排序),则不会增加成本.
from itertools import chain
result_list = list(chain(page_list, article_list, post_list))
使用itertools.chain
比循环循环每个列表并逐个追加元素要快,这是因为itertools
是在C语言中实现的.与连接前将每个查询集转换为列表相比,它还消耗更少的内存.
现在可以对结果列表进行排序,例如按日期排列(如hasen j对另一个答案的评论中所要求的). sorted()
函数方便地接受一个生成器并返回一个列表:
result_list = sorted(
chain(page_list, article_list, post_list),
key=lambda instance: instance.date_created)
如果您使用的是Python 2.4或更高版本,则可以使用attrgetter
而不是lambda.我记得曾经读过有关它更快的文章,但对于一百万个物品清单,我没有看到明显的速度差异.
from operator import attrgetter
result_list = sorted(
chain(page_list, article_list, post_list),
key=attrgetter('date_created'))
I am trying to build the search for a Django site I am building, and in that 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")
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.
Does 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))
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.
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)
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视图中合并两个或多个查询集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!