Question

I'm using Django-Tagging, and I don't exactly need a cloud, I just want a limited list of the most popular tags used in my blog entries.

Using the following:

[(tag.name, int(tag.count)) for tag in Tag.objects.usage_for_model(Post, counts=True)]

It returns an array (note I'm using Lorem Ipsum while I develop):

[(u'deposit', 5), (u'escorol', 1), (u'gratuitous', 8), (u'marquee', 2)]

But then to order and limit it I need to then do this:

sorted([(tag.name, int(tag.count)) for tag in Tag.objects.usage_for_model(Post, counts=True)], key=lambda k:k[1], reverse=True)[:10]

Is there a neater way to do this? I feel like there must be.

Was it helpful?

Solution

Django's {% regroup %} template tag might be useful for this. Assuming tags is in the context of your template:

{% regroup tags|dictsort:"count" by count as sorted_tags %}
...
{% for count in sorted_tags %}
...
    {% for tag in count %}
    ...
    {% endfor %}
{% endfor %}

OTHER TIPS

If you are using the latest version of django, you could use aggregation. http://docs.djangoproject.com/en/dev/topics/db/aggregation an example on that page ..

Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')

I find the following sorting code a bit more readable than the one you wrote. Of course it doesn't remove the source problem stated by abeyer

import operator
tags = Tag.objects.usage_for_model(Post, counts=True)
tags.sort(key=operator.attrgetter('count'), reverse=True)

If you need to pull all the tags anyway, and the limit to the top n is simply a presentation thing, Fragsworth's answer is probably the way to go. If you aren't using the remainder of the tags somewhere else, I'd argue that this is really something that should be happening in the database query...you would want to be doing an 'ORDER BY count DESC LIMIT n' on the query to avoid pulling a bunch of tags that you aren't going to use.

However, it appears that django-tagging is hard coded to always group/sort by tag ids and names. I'd say the right solution is to file a bug against that, and get an api exposed that will give you back the top n tags.

I use raw sql for this:

trends = Tag.objects.raw("select tagging_tag.id, count(object_id) as counter from tagging_tag left join tagging_taggeditem on tagging_tag.id = tagging_taggeditem.tag_id group by tagging_tag.id order by counter DESC limit 10")

My approach for getting top tags in Django-Tagging is:

top_tags = Tag.objects.annotate(num=Count('taggit_taggeditem_items')).order_by('-num')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top