Django: выходная агрегация агрегации, упорядоченная по количеству - PullRequest
2 голосов
/ 25 августа 2010

Я пытаюсь вывести следующие данные в моих шаблонах 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)

Какой самый простой способ сделать это?

1 Ответ

0 голосов
/ 25 августа 2010

Это решение сработало для меня.Вам нужно будет настроить его, чтобы передать его в шаблон.

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 %}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...