Django-like filters for Kid (and Genshi)

This post is deprecated and superseded by this post.


I’ve had a look recently at Django’s templates. I know most of my readers are fans of TurboGears, so if you are one of them, hold yourself from throwing tomatoes at me – I was only playing with it. It was nothing serious.

Then, I came back to Kid, and started to miss Django’s filters. These filters are a lot like UNIX pipes. You can do things like: {{ identity.is_anonymous() | yes_no }}. The output of this will be the value returned by is_anonymous() after being processed by the yes_no filter, which translates a boolean to either “yes” or “no”.

Some filters can do really cool stuff. For instance, consider this:

  • {{ file_size | filesizeformat }}: this would print the size in a human-readable format (i.e. 17 KB, 102.4MB and so on).
  • {{ story.text | escape | linebreaks }}: this will escape all ampersands from the text and then convert all newlines to <p> and <br/>. This also demonstrates that filters can be chained.
  • You have {{egg_count}} egg{{egg_count | pluralize}} left: will pluralize the egg noun with the suffix ‘s’ if egg_count is not one.

“But you can achieve the same by using the existing functional notation!”, I see you thinking. “You can do {{ linebreaks(escape(story.text)) }}. And it has the benefits of using a pure Python expression”. That’s right. But having pipe-notation:

  • is 217% more fun, since it is more intuitive and readable
  • makes it easy to build a standard library of filters which can be commonly used, to the benefit of the frameworks’ users.
  • makes it easy to add project-specific filters, without having to pass them as a template variable (they aren’t).
  • adds a new dimension to Kid or Genshi. Currently they work great on the XML level, which is their primary design goal. But a bit lacking on text interpolation capabilties. The stuff surrounded by those XML tags also matters 🙂

Then, I thought that there should be no reason that this will not be easy to implement with Kid (or Genshi). Fast forward 30 minutes, and it is now possible to do all the above in Kid. To comply to Kid and Python syntax, it is done with double pipes:

${ story.text || escape || linebreaks }

or

${ story.link || urlize }

The last one converts URLs in the text to a clickable link.

To get a rich set of filters to start with, I just borrowed Django’s default filters module. It was fairly easy to disconnect the dependency of most on them on Django. I threw away the rest for the time being. Adding your own filter is also extremely easy. You can just add to controllers.py the following:

def handle_shorturl(s):
    """Returns the URL without the query string"""
    return s.split('?')[0]

from kid.filterslib import register_filter
register_filter('shorturl', handle_shorturl)

If you’d like to start playing with it as well, I’ve prepared two patches, against Kid 0.9.3 and Kid 0.9.4:

To apply the patch, just cd into the kid directory and type: patch -p1 < djangokid-0.9.4.patch.

For a superset of what is currently implemented, see: Django built-in filter reference.

UPDATE: I've added also a patch for Genshi.

I'm looking forward for your feedback.

This post is deprecated and superseded by this post.
This entry was posted in turbogears. Bookmark the permalink.

81 Responses to Django-like filters for Kid (and Genshi)

Leave a Reply

Your email address will not be published. Required fields are marked *