In my earlier post, I walked you through the process I took to adapt this blog, with its existing data, to include tagging under the hood. In this post, I will cover the process of making the tags useful to your visitors.

The first thing to do is make a view to filter your model, or queryset, by tag. You have it easy because django-tagging includes a view built on top of django.views.generic.list_detail.object_list. You can add a tag filtered list as easily as adding a line like this to the urlpatterns in your urls.py:

(r'^tag/(?P<tag>[^/]+)/$', 'tagging.views.tagged_object_list',
    dict(queryset_or_model=MyModel)),

Going to http://yourdjangosite/tag/python/ would now bring up a list of MyModel instances featuring a python tag, assuming you have a myapp/mymodel_list.html template written up. How will your users navigate to this view? On this blog, I first have a collection of links under each post. These are simple to make. The code is something like this in the template:

{% load tagging_tags %}
<div>
    Tagged as:
    {% for tag in object.tags %}
        <a href="/tag/{{ tag }}/">{{ tag }}</a>
    {% endfor %}
</div>

On this blog, I also have a nice list of tags on the right with the count of posts bearing each tag. Here is the code for this:

{% load tagging_tags %}
<div class="header">Tags</div>
<div class="indent">
{% tags_for_model blog.Entry as entry_tags with counts %}
{% for entry_tag in entry_tags %}
    <div>
        <a href="/tag/{{ entry_tag }}/">{{ entry_tag }}</a>
        <span class="tag_count">({{ entry_tag.count }})</span></div>
{% endfor %}
</div>

That is just too easy, but maybe you want a tag cloud, like the one on my other site. Here is the code for the tag cloud from that very site:

{% load tagging_tags %}
<div class="tagbox">
    <div class="header">Filter by Tag:</div>
    <div class="group">
        {% tag_cloud_for_model deltad.Entry as entry_tags with steps=10 min_count=1 distribution=log %}
        {% for tag in entry_tags %}
            <a class="tag{{ tag.font_size }}" href="/tag/{{ tag }}/">{{ tag }}</a>
        {% endfor %}
    </div>
</div>

The tag_cloud_for_model tag gives me a entry_tags object with 10 levels of size distributed in logarithmic order as long as there is at least one entry bearing the tag. If you look carefully, you will notice that I am using the tag.font_size to classify my anchors. You can do whatever you want with this number. I just like to keep all appearance information in CSS.

Posted by Tyler Lesmann on March 9, 2009 at 8:17
Tagged as: django python
Comments
#1 Maximillian Dornseif wrote this 3 years, 1 month ago

I suggest using a href="/tag/{{ tag|urlencode }}/" to lessen the XSS risk.

#2 Tyler Lesmann wrote this 3 years, 1 month ago

Note that on Django 1.0 and later, context auto-escaping enabled by default. You would have to turn off auto-escaping explicitly to have XSS vulnerability here.

http://docs.djangoproject.com/en/dev/ref/templates/builtins/#autoescape

#3 dishpig wrote this 2 years, 11 months ago

I can't get this page to work at all. I've managed to get the previous part of this tute working, but this one fails at every step:

1. What to put into myapp/mymodel_list.html ? I can get the page up, but there's no data in it...how do I refer to the data that's being passed back? In views.py I can see what I'm passing to any particular template. What am I passing to mymodel_list.html? tagged_object_list?

2. For the tag cloud listed last (not tried the middle two yet), I get one of two errors:
project.mymodel fails (MyModel is an abstract model...): tag_cloud_for_model tag was given an invalid model: myproj.MyModel ?

2b. If I remove the myproj, and just have MyModel, I then get an error like "Caught TypeError while rendering: get_model() takes at least 3 arguments (2 given)" ??

#4 dishpig wrote this 2 years, 11 months ago

Don't mind me on #2 - it should have been myapp.mymodel .... grrr....

#5 Tyler Lesmann wrote this 2 years, 11 months ago

@dishpig:

The *tagging.views.tagged_object_list* view gives you the same context as *django.views.generic.list_detail.object_list*. You can access the list of tagged model instances through *object_list*. Here's snippet from this blog's source:

http://paste.pocoo.org/show/225709/

http://docs.djangoproject.com/en/dev/ref/generic-views/#django-views-generic-list-detail-object-list

Post a comment