Not evaluating {{ and }} in templates

512 views
Skip to first unread message

Ben

unread,
Nov 23, 2010, 6:04:40 PM11/23/10
to Tornado Web Server
Some of the javscript templating plugins (Mustache, jQuery Templates,
underscore.js templates) want to use {{ and }} to control their
template flow. See this jQuery Templates docs for reference:
http://api.jquery.com/category/plugins/templates/

I need to render these javascript templates verbatim without Tornado
parsing these special characters. I didn't see any way in the template
code to say "hey, don't try to convert this into python code." Am I
missing something?

I'm working around this for now by reading in a file with just my
javascript template and passing it to the tornado template as a
paramater. Is there a better way to do this?

Ben Darnell

unread,
Nov 24, 2010, 2:32:05 AM11/24/10
to python-...@googlegroups.com
We don't currently have a proper way to escape braces in tornado
templates. I'd accept a patch to add some sort of escaping, but I
think that in general you may be happier putting these javascript
templates in separate files that don't get processed by tornado's
template engine since the syntaxes clash. If you only want to do this
occasionally and separate files aren't worth it you can work around
the lack of escaping by putting the {{ inside an expression, i.e.
{{"{{"}}.

-Ben

Jacob Kristhammar

unread,
Nov 24, 2010, 2:37:36 AM11/24/10
to Ben, Tornado Web Server
There's an open issue on this topic in jQuery tmpl[1]

Currently I worked around this by passing an additional object to my templates that does a little getattr magic to generate the js-tmpl tags that clash with Tornado's templating system.[2]

For some reason I started having it as a UIModule but you could remove UIModule from the bases of JQTmpl class in the uimodules.py[2] an pass in an instance of this class to any template manually.

The general idea is that instead of writing e.g. {{ if foo }} in the js tmpl, you would write {{ j.If("foo") }} in the tornado template.
Its not super-pretty but it lets you mix the two templating systems pretty freely. To insert a close tag you would have to write {{ j.endIf }}.

Cliff Wells

unread,
Nov 24, 2010, 3:00:48 AM11/24/10
to python-...@googlegroups.com
A simple workaround would be to replace the string constants "{{" and
"}}" in the template._parse() function with module variables. This
would allow the library user to change those to alternate delimiters if
needed. At most this represents changing a half dozen lines of code.

EXPR_START = "{{"
EXPR_END = "}}"

...

def _parse(reader, in_block=None):
...

if start_brace == EXPR_START:
end = reader.find(EXPR_END)
if end == -1 or reader.find("\n", 0, end) != -1:
raise ParseError("Missing end expression %s on line %d" % (EXPR_END, line))


Then the library user simply needs to do:

from tornado import template
template.EXPR_START = "{<"
template.EXPR_END = ">}"

Regards,
Cliff

--
Cliff Wells <cl...@develix.com>

Cliff Wells

unread,
Nov 24, 2010, 3:22:26 AM11/24/10
to python-...@googlegroups.com
Actually that won't quite work. I spent another minute reading the
code and I see it's using a lookahead to determine if the next character
is part of a delimiter or not. It would need some additional logic at
the readahead point:

So this (line 473):

if reader[curly + 1] not in ("{", "%"):

would need to become:

if reader[curly + 1] not in (EXPR_START[1], "%"):

although this construct makes me want to abstract out the entire
delimiter logic even more (to allow for variable-length delimiters and
for changing the block delimiter as well). But that's left as an
exercise for someone who actually uses this template engine (I use
Breve).

Regards,
Cliff

Reply all
Reply to author
Forward
0 new messages