Django-Tagging - count and ordering top "tags" (Is there a cleaner solution to mine?)
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_mod开发者_JS百科el(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.
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')
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 %}
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')
精彩评论