2010-08-25 75 views
2

我試圖在我的Django模板中輸出以下數據。Django:通過計數排序的聚集輸出聚合

國家將按照故事排列順序排列。 城市將被勒令故事#下降(該國下)

Country A(# of stories) 
    City A (# of stories) 
    City B (# of stories) 

Country B(# of stories) 
    City A (# of stories) 
    City B (# of stories) 

我的模型如下:

# Create your models here. 
class Country(models.Model): 
    name = models.CharField(max_length=50) 

class City(models.Model): 
    name = models.CharField(max_length=50) 
    country = models.ForeignKey(Country) 

class Story(models.Model): 
    city = models.ForeignKey(City) 
    country = models.ForeignKey(Country) 
    name = models.CharField(max_length=255) 

什麼是最簡單的方法是什麼?

+0

我意識到是這樣做的方法很多,但不知道是否有利用Django的ORM的方式,像這樣的答案在這裏,http://stackoverflow.com/questions/ 1010848 /遍歷多維字典在Django中/ 1011145#1011145 – Maverick 2010-08-25 09:33:50

回答

0

此解決方案適用於我。你需要調整它才能將它傳遞給模板。

from django.db.models import Count 
all_countries = Country.objects.annotate(Count('story')).order_by('-story__count') 

for country in all_countries: 
    print "Country %s (%s)" % (country.name, country.story__count) 
    all_cities = City.objects.filter(country = country).annotate(Count('story')).order_by('-story__count') 
    for city in all_cities: 
     print "\tCity %s (%s)" % (city.name, city.story__count) 

更新

這裏是將這些信息發送到模板的一種方式。這一個涉及使用自定義過濾器。

@register.filter 
def get_cities_and_counts(country): 
    all_cities = City.objects.filter(country = country).annotate(Count('story')).order_by('-story__count') 
    return all_cities 

查看:

def story_counts(request, *args, **kwargs): 
    all_countries = Country.objects.annotate(Count('story')).order_by('-story__count') 
    context = dict(all_countries = all_countries) 
    return render_to_response(..., context) 

而且在你的模板:

{% for country in all_countries %} 
    <h3>{{ country.name }} ({{ country.story__count }})</h3> 
    {% for city in country|get_cities_and_counts %} 
     <p>{{ city.name }} ({{ city.story__count }})</p> 
    {% endfor %} 
{% endfor %} 

更新2

變異與模型的自定義方法。

class Country(models.Model): 
    name = models.CharField(max_length=50) 

    def _get_cities_and_story_counts(self): 
     retrun City.objects.filter(country = self).annotate(Count('story')).order_by('-story__count') 
    city_story_counts = property(_get_cities_and_story_counts) 

這可以讓您避免定義過濾器。模板代碼更改爲:

{% for country in all_countries %} 
    <h3>{{ country.name }} ({{ country.story__count }})</h3> 
    {% for city in country.city_story_counts %} 
     <p>{{ city.name }} ({{ city.story__count }})</p> 
    {% endfor %} 
{% endfor %} 
+0

謝謝,但有沒有一種自然的方式將此傳遞到我可以在模板中工作的數據結構?或者我現在需要建立一個自定義字典? – Maverick 2010-08-25 07:24:32

+0

增加了一種方法。這涉及一個過濾器。 – 2010-08-25 07:36:49

+0

我喜歡這個答案,但想知道是否有更「django」這樣做的方式。像這樣的答案,http://stackoverflow.com/questions/1010848/traversing-multi-dimensional-dictionary-in-django/1011145#1011145 – Maverick 2010-08-25 09:32:34