Django Development with Djblets: Custom Tag Helpers

I’m planning to cover all of what Django can do, but for now, let’s start simple with something most Django developers spend way too much time creating: Custom tags.

Django’s nice enough to provide a @register.simple_tag decorator for creating very basic tags that don’t take a context but do take parameters. This is great, but what if you want more? Many Django applications use the same boilerplate time and time again to create their tags, but we make it much easier.

Introducing @basictag and @blocktag.

@basictag

Ever wanted to use Django’s @register.simple_tag but needed access to the context? I’ve found far too many cases where this would be useful, but Django doesn’t make this easy. Your tag code would end up looking like this:

class MyTagNode(template.Node):
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    def render(self, context):
        arg1 = Variable(self.arg1).resolve(context)
        arg2 = Variable(self.arg2).resolve(context)

        return context['user']

@register.tag
def mytag(parser, token):
    bits = token.split_contents()
    return MyTagNode(bits[1], bits[2])

Do this a few times and it’s bound to drive you nuts. How about this instead?

from djblets.util.decorators import basictag

@register.tag
@basictag(takes_context=True)
def mytag(context, arg1, arg2):
    return context['user']

Far less code and increased readability. Hooray!

@blocktag

@blocktag aims to do the same thing @basictag does but for block tags. A block tag is a tag that contains nested content, like @spaceless or @for. This usually requires even more boilerplate than the above code fragment, except with the added complexity of having to grab the contents of the block.

We’ve condensed it down to this:

from djblets.util.decorators import blocktag

@register.tag
@blocktag
def blinkblock(context, nodelist, arg1, arg2):
    return "<blink>%s</blink>" % nodelist.render(context)

If you’ve built block tags in the past, you’ll appreciate how simple that was.

Django Development with Djblets

Django is an awesome development platform for web applications. With such features as database abstraction, template/view/url separation, built-in authentication with interchangeable backends, it’s made web development much more enjoyable.

We use Django in Review Board with much success. Over time, as we’ve come to develop new features, we realized that much of our codebase was useful outside of Review Board and, bit by bit, moved pieces into a library we call Djblets.

What does Djblets do?

A bit of everything, really. Any time we have useful functionality that isn’t tied to Review Board, we put it here.

Djblet’s feature list currently consists of:

  • Authentication improvements, making it easy to register and login in one step, seamlessly, handle password recovery, and more.
  • Flexible datagrids for displaying data in a paginated list with user-specific column customization, ordering and sorting.
  • Decorators to drastically simplify creation of simple and block template tags.
  • Caching functions for calling a function and caching the result if the data isn’t already in the cache, and a special URL pattern matcher that prevents caching of any contained URLs.
  • Unit testing utility classes.

And of course more little things here and there.

Downloading Djblets

Djblets is not a released app, but it’s pretty stable and well tested. You can check out a copy from our SVN repository, or automatically include it in your own repository through an svn:externals entry.

Djblets is licensed under the MIT license, making it usable in most projects.

Using Djblets

Over time I’ll be writing articles on using the many features of Djblets. See the other posts in the series, or dig around the Djblets source code.