开发者

Django Grouping Query

I have the following (simplified) models:

class Donation(models.Model):
    entry_date = models.DateTimeField()

class Category(models.Model):
    name = models.CharField()

class Item(models.Model):
    donation = models.ForeignKey(Donation)
    category = models.ForeignKey(Category)

I'm trying to display the total number of items, per category, grouped by the donation year.

I've tried this:

Donation.objects.extra(select={'year': "django_date_trunc('year', 
    %s.entry_date)" % Donation._meta.db_table}).values('year', 
    'item__category__name').annotate(items=Sum('item__quantity'))

But I get a Field Error on item__category__name.

I've also tried:

Item.objects.extra(select={"year": "django_date_trunc('year', 
    entry_date)"}, 开发者_如何学JAVAtables=["donations_donation"]).values("year", 
    "category__name").annotate(items=Sum("quantity")).order_by()

Which generally gets me what I want, but the item quantity count is multiplied by the number of donation records.

Any ideas? Basically I want to display this:

2010
  - Category 1: 10 items
  - Category 2: 17 items

2009
  - Category 1: 5 items
  - Category 3: 8 items


This other post looks like what you're looking for:

Django equivalent for count and group by

Depending on your Django version, you may or may not be able to use it though.


I realize you've probably already written your raw SQL, but the following came to mind when I saw the way you want to display your data:

If it's alright to do it at the template level you might be able to make strategic use of the regroup tag and length filter.

Regroup takes a "list of alike objects" so a queryset might work just fine, but the docs show a list of dictionaries, so I've used values here:

item_listing = Item.objects.values('category__name', 'donation__entry_date')
# use your favourite method to extract the year information into a key in item_listing
item_listing = ...

Now in the template, something like:

<ul>
{% for year_group in item_listing %}
    <li>{{ year_group.grouper }}
    <ul>
        {% regroup year_group.list by category__name as category_listing %}
        {% for category_group in category_listing %}
        <li>
        Category: {{ category_group.grouper }}
        Count: {{ category_group.list|length }}
        </li>
        {% endfor %}
    </ul>
    </li>
{% endfor %}
</ul>

I'm not sure if the regroup tag nests well like that (haven't tried it). Also, I have no idea how well regroup performs if you've got a lot of data, but then again, there's always caching...

If you decide to use this, make sure that you take note of the ordering gotcha mentioned in the regroup docs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜