2015-11-04 88 views
1

我想在我的Django的queryset上使用經典的數據庫GROUP_BY。django嵌套GROUP BY:返回對象

我已經看到How to query as GROUP BY in django?但區別是:

  • ,我需要得到對象的dictionnary,沒有值(實際上不是的東西通過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中的所有城市對象分組。

+0

只是出於好奇:你有沒有考慮寫原始SQL該查詢並將它傳遞給'CitiesTable.objects。原始(...)'?你不會得到一個結構化的對象,而是一個包括國家,州和城市在內的平面列表,但是當你從一個組退出並保持下一個時,你可以檢測到狀態和國家排序。此外,它會更好的表現,因爲它減少到一個查詢 – FSp

回答

1

恐怕我不知道如何用django的查詢集來解決這個問題。可能沒有解決方案,或者如果有可能涉及使用未記錄的功能。

但是,python解決方案在大多數情況下都可以。無論如何,Django可能不得不做類似的事情。

看起來你的當前代碼可能存在一個小問題。在使用itertools.groupby之前,您幾乎應該總是對您的條目進行排序 - 這是一個常見的陷阱,非常讓我驚訝,它不會自動排序。 Groupby遍歷迭代器,並在每次鍵值發生更改時創建一個新組。因此,爲了完全分組迭代,您需要先按鍵進行排序。

在這裏,你可以做使用的數據庫的整理,只需使用兩次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)