I wanted:
>> <body>
>> <div>
>> <p>
>> <?py if boolean: ?>
>> some conditional text
>> <?py #endif ?>
>> </p>
>> </div>
>> </body>
You suggested:
> What I can do is to extend Template class to add dummy 'if' statement.
> class MyTemplate(tenjin.Template):
>
> def convert(self, input, filename=None):
> self._is_first_stmt = True
> return tenjin.Template.convert(self, input, filename)
>
> def add_stmt(self, buf, code):
> if self._is_first_stmt:
> if buf and buf[-1] != "\n" and buf[-1].isspace():
> indent = buf.pop()
> tenjin.Template.add_stmt(self, buf, "if True: ##
> dummy\n")
> buf.append(indent)
> self._is_first_stmt = False
> tenjin.Template.add_stmt(self, buf, code)
> <html>
> <body>
> <ul>
> <?py if items: ?>
> <?py for item in items: ?>
> <li>#{item}</li>
> <?py #endfor ?>
> <?py #endif ?>
> </ul>
> </body>
> </html>
Thank you! That's great. The code you use to support this is not
straight-forward to me because I am unfamiliar with the inner workings
of the template class. In your example you used <?py for
item ... ?> indentation. Can you tell me if it will also work with
the indentation outside the py tag style? Like this:
<html>
<body>
<ul>
<?py if items: ?>
<?py for item in items: ?>
<li>#{item}</li>
<?py #endfor ?>
<?py #endif ?>
</ul>
</body>
</html>
The reason I would like to make sure this will still work relates to
my efforts to eliminate whitespace.
>> Another problem I have is that my django templates get pre-processed
>> with an html compressor which strips out redundant whitespace. Since
> '30% reduction' is very impressive.
> Hmm, it is difficult for Tenjin to strip spaces automatically and
> correctly.
> I don't have a good solution for this issue, but I'll try to think it.
I think this will not be too hard to fix on my end. I can write my
own simple compressor which will combine all whitespace except when it
matches "^\w*<?py". Since I have rewritten most of my inline
conditionals to use helper functions, I have relatively few <?py ?>
statements so this scheme would get me 95% of the way to my original
file sizes.
[From your reply to my email]
>> to list them all in the arguments line. What I would really like is
>> simply every ${var} and #{var} to automatically translate to
>> _context.get('var', None) instead of raising exceptions when var is
>> not passed in through the context.
> How to create your own Template class and convert "@var"
> into "_context.get('var', None)" automatically?
> def _expand(code):
> """expand '@var' into '_context.get("var", None)'"""
> return re.sub(r"@(\w+)", r"_context.get('\1', None)", code)
>
> class MyTemplate(tenjin.Template):
>
> def add_stmt(self, buf, code):
> tenjin.Template.add_stmt(self, buf, _expand(code))
>
> def add_expr(self, buf, code, flag_escape=None):
> tenjin.Template.add_expr(self, buf, _expand(code), flag_escape)
> <p>Hello #{@user or 'guest'}!<p>
> <?py if @message: ?>
> <p>#{@message}</p
Thank you again! Because of the strict indentation requirements of <?
py ?> statements I have tried to avoid them for conditionals whenever
possible. So I have a lot of constructs like:
#{(_context.get(conditional, False) and 'true text') or 'false text'}
These "conditionals" are like optional flags to the template. They
are defined true when used but undefined when not used. I don't want
to make all the callers have to know and pass in False for every
unused option. With your proposed subclass, I can at least simplify
this down to:
#{(@condition and 'true text') or 'false text'}
For me at least, that small reduction brings it down to the point
where the whole expression fits in my head. Being able to also do <p>#
{@message}</p> is a bonus!
>> Preliminary benchmarks show pyTenjin to compare extremely
>> favorably to the GAE built-in django templates. I have several
>> inline conditionals to try to translate to Tenjin helper
>> functions. After that I will be sure to post some concrete
>> performance numbers.
I have finished my initial port of my templates to pyTenjin. I am
happy to report that running on my GAE dev environment requests which
result in uncached template creation are running 10-15% quicker.
Requests which result use in memory (not memcache) cached templates
are running around 30% quicker than their in memory cached django
counterparts. It is not easily possible to measure the performance of
the gaememcached scenario on the single-threaded dev server. Since I
am reluctant to turn on profiling of the deployed application I cannot
judge that scenarios performance with respect to uncached django
performance (uncached since django does not memcache).
I would also like to point out that the 10-15% / 30% improvements are
in total request processing time. This includes significant non-
template related activities. Consequently the improvement in template
processing alone is actually some higher percentage. I chose to only
compare total request time for two reasons. First, isolating the
template processing time would be more difficult. Second, some
template frameworks incur more overhead in import processing. Because
GAE creates new runtime instances with little hesitation, I wanted to
make sure that import overhead of the template system was not
overlooked.
All in all I am quite pleased with how pyTenjin is performing. With
some of the template subclassing you have suggested, it will make it
less difficult to manage my templates. My only concern is that some
of the processing required to support #{@var} and the arbitrary
initial indentation of <?py ?> statements will erode some of the
performance gains.
Thank you very much for all your help in trying to make this work for
my situation.
Regards,
Steve