Skip to content

Instantly share code, notes, and snippets.

@mjumbewu
Created September 6, 2012 06:05
Show Gist options
  • Save mjumbewu/3651921 to your computer and use it in GitHub Desktop.
Save mjumbewu/3651921 to your computer and use it in GitHub Desktop.
An example of how to do URL resolution with django-jstemplates
# chadmasso has an interesting solution to using Django template tags in your
# Handlebars JS templates: precompile the template to Handlebars JS code, and
# then run the template through Django's template renderer.
#
# https://github.com/chadmasso/pencilthin
#
# Below are two possibilities for how a similar thing would be accomplished in
# django-jstemplate.
#
# 1) PREPROCESSOR(S)
# ---------------
#
# In the first possible way, we could create a preprocessor for those Django
# template tags that we care about:
import re
from django.core.urlresolvers import reverse
from django import template
class ReverseUrlPreprocessor(object):
# Should match strings like: {{ url 'home' }}
url_re = re.compile(r'\{\{\s*url\s+(.+?)\s*\}\}')
def reverse_url(self, match):
"""Resolve the arguments in the current context, and reverse the URL"""
unresolved_args = match.group(1).split()
resolved_args = [template.Variable(arg).resolve(self.context)
for arg in unresolved_args]
url_name, url_args = resolved_args[0], resolved_args[1:]
return reverse(url_name, args=url_args)
def process(self, content, context):
self.context = context
return re.sub(self.url_re, self.reverse_url, content)
# This is nice because (1) it makes the url tag look like a Handlebars expr
# (which you could also say is not nice), and (2) it doesn't require an actual
# Handlebars renderer, let alone one that renders to JS.
#
# 2) CUSTOM TAG
# ----------
#
# This solution is a lot like chadmasso's. However, it still compiles the
# Handlebars templates during the Django template compilation process.
import subprocess
import tempfile
from django import template
from jstemplates.base import BaseJSTemplateNode, jstemplate_tag_helper
register = template.Library()
class HandlebarsJSNode(BaseJSTemplateNode):
def generate_node_text(self, resolved_name, file_content, context):
tfile, tfilename = tempfile.mkstemp()
tfile.write(file_content)
tfile.close()
t = template.Template(subprocess.check_output("handlebars -m %s" % tfilename, shell = True))
output = t.render(context)
return output
@register.tag
def handlebarsjs(parser, token):
"""
Finds the HandlebarsJS template for the given name, compiles it to
JavaScript with the Handlebars node.js compiler, and then renders it with
the Django template system.
"""
return jstemplate_tag_helper('handlebarsjs', HandlebarsJSNode,
parser, token)
# At the moment, I prefer the latter solution EXCEPT for the fact that it
# currently requires node.js to be installed in order to work.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment