Django template utilities

In the course of working on a couple personal projects (which will be released eventually), I found myself factoring out a lot of common code and making it more and more generic, until one day I realized I had a whole separate application just waiting to be documented and bundled.

So here it is: template_utils, a collection of generic and useful tags, filters and other tools related to Django templates. Full documentation is on the project wiki at Google Code, and distributed with the download.

Even though I’m using most of the code already in my own projects, I’m still labeling this a 0.1 release and giving it a development status of “beta”; feedback and bug reports (there’s also an issue tracker over there, please don’t post bug reports in comments here) are appreciated.

Comments

Scott Atkins
April 12, 2007
#

Nice work James,

Just wondering if any of these features would be features which could be shipped with Django itself?

Could this possible live in django.contrib?

VidJa
April 12, 2007
#

Thanks, this exact topic is what kept me puzzling for hours trying to learn python and django at the same time. Your code should definitely be in Django itself

buriy
April 12, 2007
#

Please contribute this to Django right now!

James Bennett
April 12, 2007
#

I don’t personally see this as a contrib candidate; there are a lot of things in it which don’t belong in Django (and a couple which have specifically been vetoed).

Christian Jørgensen
April 12, 2007
#

Great work :)

Jeremy Dunck
April 12, 2007
#

Finding all these cool Django apps all over the interweb is kind of tough.

Perhaps there should be a DjangoForge.net.

Josh
April 13, 2007
#

@Jeremy: There is the Django snippets site with downloadable chunks of Django code.

Joel Bernstein
April 13, 2007
#

Most of these things are very useful, but I can’t help but think that the only real reason to need the “generic content retrieval” module is if your data needs outstrip the generic views, but you’re still using them anyway.

If that’s the case, the real solution is to write custom views and put the necessary data into your context, so you can get to it without resorting to MTV-breaking hacks.

Who knows, maybe I’m misinterpreting the purpose of that module, or blowing the issue way out of proportion.

James Bennett
April 13, 2007
#

Joel, the purpose of the generic content tags is to handle things like the footer on this site, which pulls out the five latest entries, links and comments. Manually putting that into every context would be a chore, but having a template tag which can do it — and, more importantly, do it in a base template so that can propagate to all the templates which extend it — makes it much simpler.

The “random object” tag is another good example; on my home page you might notice that the tagline in the title changes, and it does that through randomly selecting one on each render. Another use would be for a setup like Slashdot, where a random quote is displayed at the bottom of every page.

Similarly, the “retrieve object” tag is designed for something which needs to be in the database but also needs to be displayed on multiple pages; you might have an “about” snippet or similar which you want to maintain and update through the admin interface, but want to pull out everywhere.

You could do all of this with a fairly complex setup of context processors, but to me it feels cleaner to handle it through template tags and let template inheritance work its magic.

VidJa
April 18, 2007
#

james. this is exactly what I’m doing in my php app. fetching the last posted three images in a ‘footer’. This ‘footer’ is also scattered around the site and In thought it was rather annoying to code it into every single view again and again, violating the DRY principle completely

If anyone has other ideas, please share them or add them to the documentation since according to my colleagues i’m not the only one being puzzled over this as a new django user.

Michael
April 20, 2007
#

Thanks James for making them available to the rest of us! Think you just saved me a few more posts to the django-users group asking how to include generic content without adding lots of fluff to each view :)

Loving using Django!

Hone
May 4, 2007
#

Hows about a search engine for django snippets?

Maybe above ‘Snippets’ and ‘About’ tabs on the top right.

It takes ages navigating through the snippets.

Otherwise awesome and thanks.

James Bennett
May 5, 2007
#

I get that request about five times a day. When somebody implements a search system for Django that can run on shared hosting, I’ll happily start using it…

Roderik
May 5, 2007
#

Hi, thanks for making this code available. I am still in the process of learning Django but this makes it much easier to understand.

I was looking into adding some extra functionality by having a get_timed_objects tag, which would get two extra arguments and be able to take only past or future events based upon the field named. Maybe this is a completely wrong way of thinking but here goes anyway…

I extend your do_timed_objects function as follows: (I am not sure if this is the place to actually post all this code so I will only post the comments and changes with respect to do_latest_objects)

def do_timed_objects(parser, token):
    “””
    Retrieves the latest “num“ objects from a given model, in that
    model’s default ordering, and stores them in a context variable.

    Syntax::

        {% get_latest_objects [app_name].[model_name] [num] as [varname] [future|past] [dateField] %}

    Example::

        {% get_latest_objects comments.freecomment 5 as latest_comments past pub_date %}

    “””
    […snip…]
    return TimedObjectsNode(bits[1], bits[2], bits[4], bits[5], bits[6])

And the TimedObjectsNode class looks like this:

class TimedObjectsNode(template.Node):
    def __init__(self, model, num, varname, future, dateField):
        self.model, self.num, self.varname, self.dateField, self.future = model, int(num), varname, dateField, future

    def render(self, context):
        model = get_model(*self.model.split(‘.’))
        if model is not None:
            if future == ‘future’:
                filterString = join(self.dateField,’__gte’)
                System.out.println(filterString)
            elif future == ‘past’:
                filterString = join(self.dateField,’__lte’)

            if self.num == 0:
                context[self.varname] = model._default_manager.filter(filterString=datetime.now())
            elif self.num == 1:
                context[self.varname] = model._default_manager.filter(filterString=datetime.now())[0]
            else:
                context[self.varname] = list(model._default_manager.filter(filterString=datetime.now())[:self.num])
        return ”

When I try to use this code it doesn’t seem to work because of some string operations I do. As I am not that familiar yet with either Python or Django I don’t know if the problem is in the

filterString=datetime.now()

or in the actual joining of the two strings.

BTW I also added the ability to get all objects by passing 0 as the amount.

PS Sorry if you consider me to be ‘polluting’ your comments with such a long post. I also hope that the markdown is generating the code as actual code…

Add a comment

You may use Markdown syntax in your comment, but raw HTML will be removed. By posting a comment here, you are agreeing to the terms of my comment policy.