Way to change template engine

71 views
Skip to first unread message

pigmej

unread,
Oct 12, 2008, 3:27:27 PM10/12/08
to web2py Web Framework
Is there any way to change default template engine in web2py?

I would like to change it to something better with more features like
Jinja2

Or maybe there is a lot of undocumented things in default template
engine ?

yarko

unread,
Oct 12, 2008, 3:59:55 PM10/12/08
to web2py Web Framework
There have been several discussions on this list on the topic - for
example, look through
http://groups.google.com/group/web2py/browse_thread/thread/1ef4eea826f3a1f6/dc6d1b52b31fa196?hl=en&lnk=gst&q=template+engine#dc6d1b52b31fa196

I think a raesonable summary is:

- web2py's templating, being very close to just being Python, is
likely to continue to be default for some time;
- some people have written tools to convert skins for other templates
to convert to web2py, so if it's available graphic designs you want,
that's one way to go
- there has been talk about still allowing an interface for other
engines.

I think interest (beyond one of discussion) has not been strong enough
for someone to identify all the core web2py things that would have to
be moved into a module, and rewritten for another template engine.
This has spurned talk and work about modules for web2py, T2 being one
example. It has not yet spurned a design analysis of where all the
boundaries are, and what it would take to implement that.

As for documentation, there's Chapter 5 of the web2py book... but
basically, the template language is python, the helper functions are
named after HTML, so you can discover them and use them as you would
expect (<h2>This Heading</h2> ==> H2('This Heading') ) with all the
named paramteres that w3c defines to h2 (for example) mirrored in
H2(). There is a genshi translator (search these forums) and there
is also Massimo's quick demonstraton of a layout builder - see the
link on http://www.web2py.com . The builder has a link on it to
download the result of your layout experimentation.

Those are probably good starting places.

Hope this was helpful.

Regards,
Yarko

yarko

unread,
Oct 12, 2008, 4:11:20 PM10/12/08
to web2py Web Framework
Also - if you want to use Genshi Templates (or try to do something
similar for Jinja2), see the Genshi4web2py.py file and instructions
here:

http://mdp.cti.depaul.edu/AlterEgo/default/show/162


On Oct 12, 2:59 pm, yarko <yark...@gmail.com> wrote:
> There have been several discussions on this list on the topic -  for
> example, look throughhttp://groups.google.com/group/web2py/browse_thread/thread/1ef4eea826...
>
> I think a raesonable summary is:
>
> -  web2py's templating, being very close to just being Python, is
> likely to continue to be default for some time;
> - some people have written tools to convert skins for other templates
> to convert to web2py, so if it's available graphic designs you want,
> that's one way to go
> - there has been talk about still allowing an interface for other
> engines.
>
> I think interest (beyond one of discussion) has not been strong enough
> for someone to identify all the core web2py things that would have to
> be moved into a module, and rewritten for another template engine.
> This has spurned talk and work about modules for web2py,  T2 being one
> example.   It has not yet spurned a design analysis of where all the
> boundaries are, and what it would take to implement that.
>
> As for documentation, there's Chapter 5 of the web2py book... but
> basically, the template language is python, the helper functions are
> named after HTML, so you can discover them and use them as you would
> expect (<h2>This Heading</h2> ==> H2('This Heading') ) with all the
> named paramteres that w3c defines to h2 (for example) mirrored in
> H2().   There is a genshi translator (search these forums) and there
> is also Massimo's quick demonstraton of a layout builder - see the
> link onhttp://www.web2py.com.   The builder has a link on it to

mdipierro

unread,
Oct 12, 2008, 4:37:25 PM10/12/08
to web2py Web Framework
Yes you can as Yarko explains but:

1) your app will not be portable, since it will require the other
engine installed
2) You lose the ability to byte-code compile templates and distribute
them in a closed-source web2py app.
3) The current web2py template engine, because of bytecode compilation
and one-time parsing using only regex is faster than alternatives.
4) I will argue that other engines do not have "more features" only
"more syntax to learn"
(unless you consider a feature limiting what template designers can
do).

Anyway, I may be wrong about 4 and I do like Genshi for example, but I
fail to see the point of Jinja.
Could you tell what you like about it and why you consider it superior
to the default web2py one?

Massimo

On Oct 12, 2:27 pm, pigmej <pig...@gmail.com> wrote:

pigmej

unread,
Oct 12, 2008, 4:42:51 PM10/12/08
to web2py Web Framework
thanks for reply.

Python is templating engine - thats really good.

But I can only include file in one place and there is no way to change
anything in parrent file. That's a minus, and the minor problem for
mine.

The same thing with filters/macros. I need to use the same macro/
filter in many files. I cannot find this "option" in web2py
templates...

yarko

unread,
Oct 12, 2008, 5:00:35 PM10/12/08
to web2py Web Framework
Maybe some examples would help me better understand what you mean by
these two points.
Could you give something short?

Thanks!

Yarko

mdipierro

unread,
Oct 12, 2008, 5:01:28 PM10/12/08
to web2py Web Framework
You can do both:

1) Example of passing variables to parent.
Here is layout.html

<html><body><h1>{{=title}}</h1><p>{{include}}</p></body></html>

and here is an example of index.html

{{title='something'}}
{{extend 'layout.html'}}
Hello World

Also are variables returned by the action and defined in models are
also passed to the parent.

2) Example of a filter.
You cannot filter HTML (because it does not make sense since you write
it) but you can filter TEXT (coming from a variable for example) and
the output of helpers. For example the following filter replaces
newlines with <br />, sanitize everything else and wraps everything in
a <p>.

{{def myfilter(s):}}
<p>{{=XML(str(s).replace('\n','<br />),sanitize=False)}}</p>
{{return}}

{{=myfilter("""Any<span>html code that
you</span> like.""")
{{=myfilter(H1(SPAN('Hello\nWorld')))}}

Massimo


On Oct 12, 3:42 pm, pigmej <pig...@gmail.com> wrote:

pigmej

unread,
Oct 12, 2008, 5:20:08 PM10/12/08
to web2py Web Framework
sure,

for example in base template I define "block", then in child template
I can modify content of this block, that's useful in many,many
situations.

Secondly. Custom filters. I write python function in any file, then I
add it to jinja env and after that I can use it as a normal filter in
template.

Jinja syntax is very clean and easy ( it's similar to web2py & django
too ).

Examples in jinja:

escaping a string:
{{some_string|e}}
applying filter:
{{some_string|some_filter}}

loops:
{%for x in xrange(20)%}
(...)
{%endfor%}

as you see its really easy ( web2py is really easy too )

The blocks and easy to write and use filters are a BIG advantages of
Jinja. Other things are easy to "translate" to web2py templates, I
think.

Naturally I'm describing only basics of templates

pigmej

unread,
Oct 12, 2008, 5:30:30 PM10/12/08
to web2py Web Framework
massimo,

filters... ok but what if I need to make more operations with strings
etc, python operations, imports, parsing something ?
More lines of code.

For example I need to operate on dictionaries ( defining new, parsing
etc )

Theoretically, I can apply filters on controller side... but then
there is one ( or more ) loop more.

mdipierro

unread,
Oct 12, 2008, 5:33:46 PM10/12/08
to web2py Web Framework
Yes not very pythonic. I think the web2py way is more pythonic

blocks in layout.html:
{{myblockcode1()}} {{myblockcode2()}}
and in index.html:
{{def myblockcode1():}}<h1>Hello</h2>{{return}}
{{def myblockcode2():}}<h2>World</h2>{{return}}
{{extend 'layout.html'}}

escaping a string is the default
{{="some string"}}
or
{{=apply_filter("some string")}}

loops:
{{for x in xrange(20):}}
do whatever you want
{{pass}}

"pass" is a python keyword, "endfor" is not and it could not even be
defined within python. It seems to me jinja is reinventing the wheel
(for the second time, since Django reinvented it first).

Massimo

pigmej

unread,
Oct 12, 2008, 5:46:06 PM10/12/08
to web2py Web Framework
mdipierro

thanks for showing way for blocks

I know that escaping is default and I think there should be something
to change it -> I know about XML method.

I know for syntax in web2py already :)

The short manual on site for templating is too small, I think.

Btw. Good work with web2py. PYTHON framework not a Django ( or other )
framework ;-)

yarko

unread,
Oct 12, 2008, 5:49:34 PM10/12/08
to web2py Web Framework
This looks like only a stylistic discussion to me....

Django has this too, and Jinja you say have a "shell like" syntax of
"pipes" --- that is output of one operation feeds input of another.
n
{{ car | prime | paint }} is equivalent to {{ paint(prime(car)) }},
or for that matter {{ car.paint().prime() }}

Functionally, I don't see anything you can do one way over the
other..... it's a matter of style, convenience, what your used to,
what you like reading.

I like the "pipeline" syntax, but I learned on UNIX in the mid-70's,
so it's almost "genetic" for me to just read that. The downside to
that is that you can get lulled into putting too much processing in
the template ... precisely because it's so readable.

Having a utility function in a module, or a application local function
in a controller is - as you say - doable.

But the more worthwhile thing is thinking about what you want to do,
and putting it in a good place. And making the template as concise
as makes sense.

re: one loop more on contoller side - not sure I follow you on that.
Wherever you write the filters, they are running (in these examples)
on the server, applied similarly, and when they are done, the
resulting output is rendered into something sent out over the
network... You could look at how many "calls" you have when snippets
are in the template vs. explicitly defined utility functions, but I
think this is more about the patterns of code maintenance (and
reading) than anything...

I think it probably would not be hard to apply a transform to
templates so that you can pile up calls with the "pipeline" flavor of
showing transfer of control. But, other than end user reading - and
what it might encourage about development steps - I don't think it
materially changes anything.

Am I missing something?

Kind regards,
Yarko

On Oct 12, 4:30 pm, pigmej <pig...@gmail.com> wrote

pigmej

unread,
Oct 12, 2008, 6:13:25 PM10/12/08
to web2py Web Framework
Now I see that I can make with web2py templates almost everything :).

Massimo, I really think, You should add this recipes to howto :)

@yarko:

sometimes there is no staight way to modify something in controller.
But ok, I modify it, and then i loop them again in template -> so
there are two loops. One more than using filter in template ;)

How to write multiline python code in filter ?? I cannot find real
example for this momemt...

but maybe, replacing something in part of list/dictionary etc.

yarko

unread,
Oct 12, 2008, 6:28:01 PM10/12/08
to web2py Web Framework
understood....

I was arguing that having something like {{exterior_finish(car) }}
is not any different than {{ car | pime | paint | bake | add_trim }}
that is - where the code sits...

But in the cases you meant, yes - {{my()}} <static stuff>
{{is_nicer_all_here()}}

Thanks.

As for multilne code: write "normal" code, encapsulted in {{ }};
for output, leave left side "blank" (dumps on template, so:
{{=my_result(on_this)}}
For starters, everywhere you would have "unindent" situation in
python, in template put {{ pass }};
Actually you only need where it would be ambiguous, but for starters,
that's a good rule - after you have code working, try removing the
"pass"s you think are not necessary.... won't take long to see where
you don't need them.

For HTML helpers, they take all (?) the (optional) parameters that the
W3C defines for the HTML equivalents.

For examples, get the appliances (e.g. KPAX, others on the "Repository
of free apps" link at web2py.com)

yarko

unread,
Oct 12, 2008, 6:32:47 PM10/12/08
to web2py Web Framework
...but you can already see all that from Massimo's nice, concise
examples,

and I should not be sitting reading posts on a sunny Sunday
afternoon! I'm sure not to say much of anything smart while looking
out the window ;-)

pigmej

unread,
Oct 12, 2008, 6:39:35 PM10/12/08
to web2py Web Framework
Thanks for naswers :)

In web2py I'm beginner. I generally don't like frameworks ( Django
etc ). I prefer using routers, werkzeug or paser and jinja2 for
templates, writing everything from scratch, etc. But for web2py I can
make exception. Let's see... ;)

yarko

unread,
Oct 12, 2008, 7:00:06 PM10/12/08
to web2py Web Framework
Given that, you may NOT want to put off T2 - it's just an abstraction
layer on top of web2py that makes a lot even easier (maybe so much
that it's hard at first??? LOL)

At least peruse the T2 example wiki (I am betting you'll have a
reaction) - download from here: http://groups.google.com/group/web2py/browse_thread/thread/6d96ff197de2006f/

The T2 docs will give you an idea of the layer on top which Massimo
has put to try to make things even easier; glance at the short PDF
here:
http://bazaar.launchpad.net/~mdipierro/t2/main/files/16?file_id=docs-20080922043548-uj1qtzubnbxj3dm6-8

Base site is http://launchpad.net/t2

pigmej

unread,
Oct 12, 2008, 7:00:57 PM10/12/08
to web2py Web Framework
In Poland there is Monday 1 AM and... it's not sunny rotfl ;d

yarko

unread,
Oct 12, 2008, 7:03:12 PM10/12/08
to web2py Web Framework
Note - you can read all that wiki code in about maybe 3 minutes or
less ;-)

mdipierro

unread,
Oct 12, 2008, 7:44:35 PM10/12/08
to web2py Web Framework
@pigmaj
yes there should be more docs. For now this recipe is on AlterEgo and
in the manual. I am looking into turning AlterEgo into a real wiki
very soon.

@yarko
Yes this is mainly a stylistic difference but there are two practical
differences:

1) in Django and Jinja you cannot use Python commands, only those
defined/exposed by the template engine. This means if you need a
filter you cannot define it in the view. My experience is that it
takes some non-trivial work to define one.

2) in Django and Jinja I believe there is a logical issues with block.
Consider this layout
{{block a}}xxx{{endblock}}yyy{{block b}}zzz{{endblock}}
and this view that extends it
{{block a}}abc{{endblock}}efg{{block b}}hij{{endblock}}
The output is: "abcyyyhij"
What happens to "efg"? The template language allows you to write html
that is never overwritten, is not a comment, yet it gets lost in the
rendering. I think this is bad design.
Am I wrong?

Massimo
> ...
>
> read more >>

pigmej

unread,
Oct 12, 2008, 7:45:19 PM10/12/08
to web2py Web Framework
It makes big impression.

But in plugin_t2/modules/t2.py there is mix of ' ' (4 times space)
and tabs ( tabulations )... it shouldn't be :)
> ...
>
> więcej >>

mdipierro

unread,
Oct 12, 2008, 7:52:25 PM10/12/08
to web2py Web Framework
Oops. Will fix it. Mind that T2 is still very much beta and the API
will change.

About jinja. Despite what I said above, I do understand this is very
much an issue of subjective preference. It should work out of the box
with web2py but, if you have any issue, I will be happy help you port
it to web2py. The thing I really like about Jinja is the great the
documentation.

Massimo
> ...
>
> read more >>

pigmej

unread,
Oct 12, 2008, 7:57:11 PM10/12/08
to web2py Web Framework
@massimo

1) You are wrong, I think :)

everything without {{block}} are processed automatically, but I can
manipulate everything in block content, remove it, add etc. It's
usefull

are you sure about this output ? I cannot check it now, but I expected
something like: abcyyyefghij

2) The real wiki engine is good idea :)

3) Jinja / Django is different than web2py, so I think there is no
sense to make discusion about that. I'm user of jinja2 so, I must to
get used to web2py templates. Big advantage for "standard" python
language :)

__________

btw. Is this correct ?
{{def skroc_tytul(source):}}
{{if len(source)>40:}}
{{=source[:source[:40].rindex(' ')]+'...'}}
{{else:}}
{{=source}}
{{pass}}
{{return}}

it works as I want, but ... You know ;)
> ...
>
> więcej >>

mdipierro

unread,
Oct 12, 2008, 9:09:26 PM10/12/08
to web2py Web Framework
1) If you check it let me know. If I am wrong I would like to know.
Both ways I would find the output odd.

3) I agree. Whatever works for you. I am happy to help is needed.

Your example seems fine.
> ...
>
> read more >>

yarko

unread,
Oct 13, 2008, 9:30:44 AM10/13/08
to web2py Web Framework
:-) Yes; write Massimo a filter :-)

On Oct 12, 6:45 pm, pigmej <pig...@gmail.com> wrote:
> ...
>
> read more >>

yarko

unread,
Oct 13, 2008, 9:36:45 AM10/13/08
to web2py Web Framework
Massimo:

RE: Style: I completely agree w/ you about other templating
languages vs. python-ic templates of web2py;

What I meant was that web2py offers filters, although maybe not of the
familiar shell form {{a|b|c}}, but rather {{c(b(a))}} --- THAT style,
I argued, is immaterial...

The other stuff (and more) I am with you on... although there are
practical matters left to sort out (how true is this?) about how to
"plug-in" different layouts / styles...

Regards,
Yarko
> ...
>
> read more >>

BBi

unread,
Oct 13, 2008, 10:16:10 AM10/13/08
to web2py Web Framework
Massimo,

I like the way web2py is templating, and I hope you keep it very
simple and very pythonic. In its current version, it is easy to learn
and to use. It's OK.

IMHO, complex processing should be in nothing else than python, so the
"pipe like" syntax seems to me totally exotic.
However, complex processing can be coded in a module outside of the
view and expose a clean python API called from the view. That's also
style, but more about how we understand and apply the MVC pattern.

Regards,
Bruno

mdipierro

unread,
Oct 13, 2008, 10:27:02 AM10/13/08
to web2py Web Framework
Do not worry. There is no plan to change the template system.

If some users want to use other engines (and I understand that they
may have legacy templates they may want to use with web2py) that can
be done by calling the rendering engine in the action ad returning the
html as a string.

It is also possible to make another engine default since all actions
are wrapped by a function called

response._caller=lambda x: x()

One can redefine this is in the controller (or a model) so that if x()
returns a dict, it calls the one's favorite template engine. For
example:

def use_my_engine(a,b): use_genshi(a.view,b) if isinstance(b,dict)
else b
response._caller=lambda x: use_my_engine(response,x())

Massimo
Message has been deleted

Massimo Di Pierro

unread,
Dec 26, 2008, 5:22:47 AM12/26/08
to Massimo Di Pierro, Italo Maia, web...@googlegroups.com
ERRATA: Try this instead.

def jinja2(f):
    def _jinja2():
        d=f()
        if isinstance(d,dict):
            from jinja2 import Environment, FileSystemLoader
            env = Environment(loader=FileSystemLoader(os.path.join(request.folder,'views'))
            template = env.get_template(response.view)
            return template.render(**d).encode('utf8')
        else: return d
    return _jinja2


On Dec 26, 2008, at 3:54 AM, Massimo Di Pierro wrote:

Hi Italo,

I played with this some more. Try define the following decorator (in a model or controller)

def jinja2(f):
     def _jinja2():
           d=f()
           if isinstance(d,dist):
           from jinja2 import Environment, FileSystemLoader
           env = Environment(loader=FileSystemLoader(os.path.join(request.folder,'views',request.controller))
           template = env.get_template(response.view)
           return template.render(**d).encode('utf8')
     return _jinja2

Those controller actions marked with decorator @jinja2 will expect a Jinja2 view instead of a web2py view. Mind that you must create a view file for @jinja2.
Keep me posted on whether this works or you encounter any issue. Example

@jinja2
def index(): return dict(hello='world')

with FILE: yourapp/views/default/index.html BEGIN
Hello {{ hello }}
END

should make "Hello world".

Massimo

P.S. I am ccing the list since others may be interested


Italo Maia

unread,
Dec 26, 2008, 7:27:54 AM12/26/08
to web2py Web Framework
I tried to have the jinja2 decorator inside a separate file in
controllers, with no success. My other controller simply can't find
the other files inside his package. O.O.

Oh, about the discussion, web2py template system does not seems
pythonic to me, not at all. It is not pretty(python has to be pretty),
and does not enphasys logic outsite templates, as you'll run python
code directly inside the templates. This kind of approach has proven
bad in lot's of languages and systems, from php to jsp and more.

{{text|e}} <= pretty

{{escape(text)}} <= not so much

pretty
{% for stuff in other_stuff %}
do stuff with {{stuff}}
{% endfor %}

not so much
{{ for stuff in other_stuff }}
do stuff with {{=stuff}}
{{pass}}

mdipierro

unread,
Dec 26, 2008, 11:10:53 AM12/26/08
to web2py Web Framework
Controllers do not see code in other controllers, for logical reasons,
since they act on different requests.
Controllers only see code in models. You need to put the code in a
model file or in a module. If you put in a module you need to modify
it so that request, response are passe to the decorator.

About being pythonic.... I agree and disagree:

You say

> {{text|e}} <= pretty
>
> {{escape(text)}} <= not so much

Fine but none of those examples is web2py-ese. This is the equivalent
code in web2py:

{{=text}}

In web2py text is escaped by default. It is a MUST of security.

You also say

> pretty
> {% for stuff in other_stuff %}
> do stuff with {{stuff}}
> {% endfor %}
>
> not so much
> {{ for stuff in other_stuff }}
> do stuff with {{=stuff}}
> {{pass}}

Again, none of those is valid web2py-ese. In web2py you do

{{ for stuff in other_stuff: }}
do stuff with {{=stuff}}
{{pass}}

I find the second better because it uses python keywords instead of
made up keywords (endfor?).

The main problem I have with Django and Jinja is logical. Here is an
example

IN DJANGO:

layout.html:
<html><body><h1>{% block test %}nothing{% endblock %}</h1></body></
html>

index.html:
{% extends 'layout.html %} hello {% block test %}world{% endblock %}

renders as "<html><body><h1>world</h1></body></html>"

Where does hello go? Logically this is a problem.

IN WEB2PY
layout.html:
<html><body>{{include}}<h1>{{test()}}</h1></body></html>

index.html:
{{extend 'layout.html'}} hello {{def test():}}world{{return}}

renders as "<html><body> hello <h1>world</h1></body></html>".

The extending layout is {{include}}d in a specific point so any
leftover text is inserted there. No text gets lost.
Moreover in web2py blocks are functions (this is more pythonic) and I
can even pass variables to them.

Massimo


limodou

unread,
Dec 27, 2008, 3:57:07 AM12/27/08
to web...@googlegroups.com

Most I agreed with Massimo. In Italo Maia email, he said he don't like
python code in template, but I like. Pure Python code is not beautiful
and it's not pythonic? You'll need to learn another template language
when you can use Python code in template. And you can even get all
powerful of Python. That's a great thing. Many template systems
support python code, except django one.

And rencently I'm working on making web2py template supports block tag
just like django. Say you have a parent template, looks like:

This base.html:

<html>
<head>
<title>{{block title}}Untitled{{end}}</title>
</head>
<body>
{{block main}}{{end}}
</body>
</head>

Here I defined two block title and main.

This is child template -- index.html:

{{extend "base.html"}}
{{block main}}<h1>Hello, Uliweb</h1>{{end}}

I defined main block, so when you render index.html, this main block
will replace the one defined in base.html. Because there is no title
block defined in index.html, so the title block defined in base.html
will be remained.

But use block support will break the {{include}} usage.

I'm using this new template module in my project uliweb. And the
module is in http://code.google.com/p/uliweb/source/browse/trunk/uliweb/core/template.py.
And I also made other changes, for example: parse_template will be
template_file, and the parameters are also different. But the syntax
of template tags are similar.

Maybe it's useful for someone.

--
I like python!
UliPad <<The Python Editor>>: http://code.google.com/p/ulipad/
UliWeb <<simple web framework>>: http://uliwebproject.appspot.com
My Blog: (new)http://http://hi.baidu.com/limodou
(old)http://www.donews.net/limodou

Reply all
Reply to author
Forward
0 new messages