Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Allow template directives to span multiple lines #326

merged 1 commit into from

3 participants


Removes the requirement that {% and %} be on the same line. I'm sure there's a good reason the check was already in there, since it was clearly an extra piece of code that looked quite purposeful, but it was such a small change that I implemented it anyway, and am prepared to be shot down.


We don't want to let you insert multi-line statements into the generated code, so we'd need to either replace newlines with spaces or parse the expression to make sure it's something python would recognize as a single statement spanning multiple lines (parens, backslashes, etc).


If I'm interpreting what you've said correctly, you mean that we're fine, theoretically, with single statements spanning multiple lines, like:

{{ foo(bar,
       baz) }}

but since multiple statements in a single directive would generate invalid Python:

{{ foo(bar)
   bar(qux) }}

we can't allow the first case. But can't you already insert multiple statements that break generated code with the ; separator? It's intuitive enough that only rvalues are allows in {{...}} expressions, and each {%...%} obeys its own special syntax anyway. Either way, multiple statements in a single directive will cause an error; this patch moves the error-reporting to Python, while allowing the "good" kind of multi-line statement.


Yeah, python will still catch the error, but a SyntaxError from the generated code is a much less friendly error message than "missing end tag on line X" (especially since the error is likely to be something misleading like bad indentation). I don't feel too strongly about it, but personally I'm inclined to keep the one-line restriction.


I see your point, but I'd still rank added functionality above clearer error messages.


Good error messages are a feature - just see clang vs g++ (tornado.template's error messaging is pretty bad right now, but that's no reason to make it worse). And this change doesn't let you do anything with templates that you couldn't do before, it just lets you make it slightly prettier.


I'd rather have prettier templates than a nicer presentation of an error that I'll never run into since I know what I can and can't put in multiline template directives.

I think this could be implemented as an optional feature, off by default, and the documentation for the option could explain what is allowed in multiline directives. The option would be a member of Template and BaseLoader, like autoescape is. This way people wouldn't run into the confusing syntax error, and those of us who really want multiline directives could have them.

I've already added the feature to a fork of tornado I'm using in a project, and I'd be happy to contribute the documentation update as well.

@bdarnell bdarnell merged commit c95be87 into tornadoweb:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 3, 2011
  1. @alekstorm
This page is out of date. Refresh to see the latest.
Showing with 2 additions and 2 deletions.
  1. +2 −2 tornado/
4 tornado/
@@ -579,7 +579,7 @@ def _parse(reader, template, in_block=None):
# Expression
if start_brace == "{{":
end = reader.find("}}")
- if end == -1 or reader.find("\n", 0, end) != -1:
+ if end == -1:
raise ParseError("Missing end expression }} on line %d" % line)
contents = reader.consume(end).strip()
@@ -591,7 +591,7 @@ def _parse(reader, template, in_block=None):
# Block
assert start_brace == "{%", start_brace
end = reader.find("%}")
- if end == -1 or reader.find("\n", 0, end) != -1:
+ if end == -1:
raise ParseError("Missing end block %%} on line %d" % line)
contents = reader.consume(end).strip()
Something went wrong with that request. Please try again.