django中嵌套的GROUP BY:返回对象

时间:2015-11-04 17:57:07

标签: python django itertools

我正在尝试在Django的查询集中使用经典数据库GROUP_BY。

我已经看过How to query as GROUP BY in django?,但区别在于:

  • 我需要获取对象的词典,而不是值(实际上不是values()返回的事物的类型)。
  • 我需要获得一个嵌套字典(即,我需要GROUP_BY上的GROUP_BY)。

我的模特:

class CitiesTable(models.Model):
    country = models.TextField() 
    region_or_state = models.TextField() 
    city = models.TextField() 

我希望按country进行分类,然后在其中region_or_state进行分类,其中包含city的列表:

我想要

{'USA':
    {'California': ['San Francisco', 'Los Angeles', ...],
     'Texas': ['Dallas', 'Houston', ...},
 'Germany':
     {'Bavaria': ['Munich', 'Nuremberg', ...}
}

但是,如前所述,列表中的城市应该是对象

我没有找到如何在Django中获取它,所以在python中使用itertools,我已经成功用于外部GROUP_BY: (帮助我:How to convert tuple to a multi nested dictionary in python?):

from itertools import groupby

def show_cities(request):
    queryset = CitiesTable.objects.all()
    grouped_cities = []
    unique_countries = []
    for k, g in groupby(queryset, lambda x: x.country):
        grouped_cities.append(list(g))
        unique_countries.append(k)
    return render(request, 'cities/show_cities.html', 
                  {'cities':grouped_cities, 'countries':unique_countries})

但我没有设法将所有城市对象归为region_or_state

1 个答案:

答案 0 :(得分:1)

我担心我不知道如何用django的查询集来解决这个问题。可能没有解决方案,或者它可能涉及使用未记录的功能。

但是,python解决方案在大多数情况下都可以。无论如何,Django可能不得不做类似的事情。

您当前的代码可能存在轻微问题。在使用itertools.groupby之前,您几乎总是要对条目进行排序 - 这是一个常见的陷阱,以至于我很惊讶它不会自动排序。 Groupby遍历iterable,并在每次键值更改时创建一个新组。因此,要完全对可迭代组合,您需要先按键排序。

您可以在此处使用数据库进行排序,只需使用groupby两次:

queryset = CitiesTable.objects.order_by('country', 'region_or_state')

countries_dict = {}

for country, group in groupby(queryset, lambda x: x.country):
    countries_dict[country] = {}
    for region, inner_group in groupby(group, lambda x: x.region_or_state):
        countries_dict[country][region] = list(inner_group)