在Django中创建查询集列表的最佳方法是什么?

1 投票
3 回答
2257 浏览
提问于 2025-04-17 11:11

我有一个模型类叫“Place”,里面有一个字段是“state”,我想要获取一个按数据库中所有不同状态分组的查询结果列表。

我现在是这样做的:

place_list = []
places = Place.objects.distinct('state')
[place_list.append( Place.objects.filter(state=p.state) ) for p in places]

有没有更好的聚合命令可以用来优化这个?这样做的最佳方式是什么?

~ 使用 Python 2.6,Django 1.3.1

3 个回答

0

你没有正确使用列表推导式。列表推导式不是用来重复动作的,而是用来创建列表的。所以我会这样做:

places = Place.objects.distinct('state')
place_list = [Place.objects.filter(state=p.state) for p in places]

这和你之前做的其实是一样的,只是我正确地使用了列表推导式。

3

你可以先获取所有州的值(这里的values_list工具非常好用):

states = Place.objects.values_list('state', flat=True).distinct()

然后对每个州做你之前做的事情,不过这次用你之前的列表推导式的结果,省去 .append() 这个步骤。

place_list = [Place.objects.filter(state=state) for state in states]

这样虽然还是会查询数据库,次数是州的数量加一,但你只是在一开始就执行了查询。place_list中的查询集对象会保持懒加载,直到你真正使用它们时才会被计算出来。

注意:@pastylegs 提到的在模板中使用regroup标签的建议,可能是我们说过的最有见地的内容。我的回答主要是想让你了解一下 values_list 和列表推导式。

3
from collections import defaultdict

places_by_state = defaultdict(list)
for place in Place.objects.all():
   places_by_state[place.state].append(place)
list_of_places_by_state = places_by_state.values()

这样做只会让数据库查询一次,而不是像你原来的版本那样每个状态都查询一次(假设你用到了所有的结果)。不过,这样你得到的结果是一个列表的列表,而不是一个查询集的列表。

撰写回答