For those not following along, I’ve been recreating LinuxLaboratory.org using Django. It’s my first Django project that you could call “real work”. I’ve been using the Django documentation, various blogs, and the 2nd edition of “Practical Django Projects”, which has given me a lot of ideas, and a lot of actual code. Some of it worked, some of it didn’t, some of it didn’t do things the way I wanted, and some of it was left as an exercise to the user. This was the case with some of the django-tagging-related stuff, which has been broken on the site for a while.
I finally got tired of tagging not working properly on LinuxLaboratory.org, so I started diving into the code and found that one of the things I wanted to do was actually pretty darn easy. In the process, I thought of something else I’ll probably implement later as well. Not *all* of my problems are solved, but I’m on my way!
So, Linuxlaboratory is made up of three different sections: a blog, which is its own app, a “Code” area which is another separate app, and a content management system (flatpages right now) that will handle storing republished articles when I get around to importing them all.
I enabled tagging on everything. I’m not solidly in one camp or the other on the whole “Tagging everything is bad” debate. Rather than theorize, I decided to give it a go and see how it does. My guess is that once I add a search box it will rarely actually be used, but what do I know?
The problem this presented me with was trying to figure out a way to present the user with one big monstrosity of an “index lookup” page, which would list all of the tags, and for each tag, list links to anything of any content type that was tagged with it. I understand that this could become unwieldy at some point, but if I need to I suppose I can pretty easily paginate, or present alphabet links, or perhaps both!
Though I understood the potential for future disaster, it still bothered me that I couldn’t find a quick answer to the question, so here it is for those wanting to do something similar with django-tagging. For reference, my tag index page is here.
Template Tags in django-tagging
I had actually started creating a custom template tag, and was looking at the Django docs, which stated “a lot of apps supply custom template tags”. Duh! I cd’d into the tagging directory, and there was a directory called “templatetags”. The tagging_tags.py file inside was pretty well documented, and the tag I was about to write myself is called ‘tagged_objects’. Here’s the docstring for that tag:
“””
Retrieves a list of instances of a given model which are tagged with
a given “Tag“ and stores them in a context variable.Usage::
{% tagged_objects [tag] in [model] as [varname] %}
The model is specified in “[appname].[modelname]“ format.
The tag must be an instance of a “Tag“, not the name of a tag.
Example::
{% tagged_objects comedy_tag in tv.Show as comedies %}
“””
Perfect. I already had a tag_list.html template (which, if memory serves, is one of the things left as an exercise to the user in Practical Django Projects), and it listed the tags in use on the site, but instead of linking off to a ‘tag_detail’ page for each tag, I envisioned something more interesting. I’m not there yet, but this index page is step one.
Putting Together a Template
What I needed to do was simply {% load tagging_tags %}, and then call the {% tagged_objects %} tag with the proper arguments, which consist of a tag *object* (not a tag name), the model you want to grab instances of, and a variable name you want to store the instance in. Here’s the content block from my tag_list.html:
{% block content %} {% for tag in object_list %} <div id="entry"> <p>{{ tag.name }}</p> <ul> {% load tagging_tags %} {% tagged_objects tag in monk.Entry as taggedentries %} {% for entry in taggedentries %} <li><a href="{{ entry.get_absolute_url }}">{{ entry.title }}</a></li> {% endfor %} {% tagged_objects tag in ray.Snippet as taggedsnippets %} {% for snippet in taggedsnippets %} <li><a href="{{ snippet.get_absolute_url }}">{{snippet.title}}</a></li> {% endfor %} </ul> </div> {% endfor %} {% endblock %}
So, the view I’m using supplies Tag objects in a variable called object_list. For each Tag object, I spit out the name of the tag. Underneath that on the page, for each tag, there’s an unordered list. The list items are the Entries from my “monk” application, and my Snippets from my “ray” application. I hope reading this template along with the bit above from the docstring for the template tag helps someone out. And check out the other tags in tagging_tags.py as well!
Rome Wasn’t Built in a Day
Of course, there’s still an issue with my particular implementation. Tagging was originally implemented specifically for the entries in the “/weblog/” part of my site. However, now that they’ve been applied to things in the “/snippets/” part of my site, this page doesn’t *really* belong in either one. However, if you go to the page, you’ll see that the “Blog” tab in the navigation bar is still highlighted. I’ll figure out what to do with that at some point. Until then, enjoy, and if you have any input or wisdom to share, please leave comments! Also, you should follow me on twitter!