Personal blog of Miguel Araujo

Using jQuery templating ICanHaz.js with Django

When working on a Django project with an important part of the user experience based on AJAX, you better use a frontend templating language. The same way Django has a templating language that we use to populate values easing your coder’s life, jQuery has client side alternatives. One of these plugins and my personal favorite is ICanHaz.js created by @HenrikJoreteg. It’s only 4.4 Kb.

ICanHaz.js syntax will be very familiar to Django devs, because a variable is defined using double curly brackets {{ variable }}. But I will not enter into details, the project has very easy to follow setup instructions and code examples.

When people start using ICanHaz.js in their Django templates, they have a very hard first time trying to get it to work. The problem is simple, Django and ICanHaz.js share the same variable definition, so Django interprets the script templates, breaking them.

When I found this out, I looked over the Internet until I found a fix by Eric Florenzano (@ericflo). He coded a templatetag called verbatim, that avoids that Django interprets all content within the block tag. He published it as a gist in Github. You simply have to put this within one of your app’s templatetags directory. The way you use it in a template:

{% verbatim %}
<script id="user" type="text/html">
<p class="name">Hello I'm {{ name }}</p>
<p><a href="{{ twitter }}">@{{ twitter }}</a></p>
</script> {% endverbatim %}

simple, right? Well, I recently work on an enhancement for this gist. Eric Florenzano’s version of the verbatim tag escapes everything, which means that you can’t use tags like {% url %} {% csrf_token %} or others. These are tags and not variables, so I didn’t see any reason for not having them around. Therefore I forked Ericflo’s gist and added tags support. Now you can do:

{% verbatim %}
   <script id="user" type="text/html">
      <a href="{% url addItem %}">Add Item</a>
{% endverbatim %}

Working on this wasn’t as easy as other tags I have worked on. I had to go inside the guts of django.template.defaulttags and django.template.base (former in Django 1.2) to understand how the Lexer, Token, Parser, Filter/Tag, Node, NodeList, Template structure in Django works. I couldn’t just simply parse the Tokens and build a NodeList, I had to write my own template parser and I based my code on Parser.parse. Pretty much I extracted the bits I needed from there.

blog comments powered by Disqus