Django:按计数排序的聚合的输出聚合

发布于 2024-09-16 00:57:26 字数 669 浏览 3 评论 0原文

我正在尝试在 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)

最简单的方法是什么?

I'm trying to output the following data in my django templates.

Countries would be ordered descending by # of stories.
Cities would be ordered descending by # of stories (under that country)

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

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

My models are the following:

# 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)

What's the easiest way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

☆獨立☆ 2024-09-23 00:57:26

这个解决方案对我有用。不过,您需要对其进行调整以将其传递给模板。

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 %}

This solution worked for me. You will need to tweak it to pass it to a template though.

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)

Update

Here is one way of sending this information to the template. This one involves the use of a custom filter.

@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

View:

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)

And in your template:

{% 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 %}

Update 2

Variant with a custom method in model.

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)

This lets you avoid defining a filter. The template code changes to:

{% 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 %}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文