2012-02-03 71 views
0

我正在創建一個應用程序,人們可以在其中爲城市發佈帖子。我想爲國家/地區創建一個視圖,該視圖將顯示有海報的城市列表以及每個城市已經制作了多少張海報。Django查詢和分組

我有一個國家表和一個國家的外鍵的城市表。我也有一個海報表,帶有城市表的外鍵。

這成功地給了我一張海報清單,但是如何將它們分組爲城市並通過?在該模板中,我希望能夠顯示該城市的城市名稱,海報圖片以及該城市的海報總數,爲該國海報製作的每個城市。

def country_page(request, country_name): 
    country = get_object_or_404(Country, name__iexact=country_name)  
    posters = Poster.objects.filter(city__country=country)   
    variables = RequestContext(request, { 
     'location' : country, 
     'posters' : posters, 
    }) 
    return render_to_response('country_page.html', variables) 

任何幫助,將不勝感激。

回答

0

你在找什麼是在sql land中的'group by'。

下面的線程有一些有趣的見解,底線是你需要原始SQL做一個真正的團體,但我懷疑你的需求,你可以做一個小的後處理做分組:

posters = Poster.objects.filter(city__country=country) 
poster_cities = {} 
for poster in posters: 
    if city not in poster_cities: 
     poster_cities[city] = [] 
    poster_cities[city].append(poster) 

現在你可以通過城市獲得海報這樣從模板中使用:

for city in sorted(poster_cities.keys()): 
    city_posters = poster_cities[city] 
    city_poster_count = len(poster_cities[city]) 

背景:

How to query as GROUP BY in django?

0

在原始的sql中,你應該使用「group by」等來完成它,但對於django,你應該查看模型的聚合函數。

https://docs.djangoproject.com/en/dev/topics/db/aggregation/

我遇到了類似的問題,前幾天,這我是如何解決它。您首先從特定條件過濾對象,然後指定所需的字段,最後進行計數,以瞭解總行數。

您的解決方案可能看起來類似的東西:

posters = Poster.objects.filter(city__country=country).values('city_name','poster_image',..).annotate(total=Count('city')) 
+0

難道你不應該從城市計數嗎? – Raekkeri 2012-02-03 08:40:12

+0

噢,對不起。我從我自己的項目中獲取了這些代碼,並且錯誤地更改了參數。 – Vannen 2012-02-03 08:53:18

0

這也可以在代碼中實現,而不是所有的SQL,但考慮到你的應用程序的性質 - 可能有很多海報中很多城市 - 這個解決方案很容易佔用太多的系統資源。但這裏有一個快速的片斷:

key = lambda poster: poster.city 
posters = Poster.objects.filter(city__country=country) 
posters = sorted(posters, key=key) 
di = {} 
for k, g in itertools.groupby(posters, key): 
    di[k] = list(g) 

現在di包含每個城市的鑰匙,所有的海報作爲值的列表。

0

這將返回城市,每個海報的該城市的數量:

cities = City.objects.filter(country=my_country).annotate(num_posters=Count('posters')) 

然後你就可以循環的模板:

<h1>{{ country }}</h1> 
{% for city in cities %} 
<p> 
    {{ city.name }} - {{ city.num_posters }} posters 
    {% for poster in city.posters.all %} 
     <img src="{{ poster.image.url }}"> 
    {% endfor %} 
</p> 
{% endfor %} 

現在,上面的代碼分別取海報每個城市,這可能沒有效率。爲了解決這個問題,您可以使用prefetch_related(如果你能負擔得起使用Django主幹),或手工做自己,就像here

0

有了你已經有了你可以在模板中使用regroup的代碼,類似:

{% regroup posters by city as city_list %} 

<ul> 
{% for city in city_list %} 
    <li>{{ city.grouper }} ({{city.list|length}}) 
    <ul> 
     {% for poster in city.list %} 
     <li>{{ poster.image}}</li> 
     {% endfor %} 
    </ul> 
    </li> 
{% endfor %} 
</ul> 

請注意,您需要在您的視圖中按城市排列海報查詢。