Multi Engine Template System (Django/Cheetah/Mako/Myghty/Genshi)

298 views
Skip to first unread message

justquick

unread,
Nov 14, 2007, 12:19:58 PM11/14/07
to Django users
Recently I have been in search of an alternative to the Django
templating engine. Sure the engine is well produced and has many
features, but it lacks certain functionality that other engines
provide, like direct python syntax and parameter passing. Allowing
Django to use these other engines would increase its extensibility
beyond custom templatetags and filters. The author of a website might
be more comfortable with a template system that they are already
familiar with instead of Django's, however handy it may be. That being
said, I have investigated the implementation and efficiency of
rendering templates with different engines inside the Django
environment.

I conducted a set of trials to examine rendering speed for each of
five engines; Django/Cheetah/Mako/Myghty/Genshi. The tests were run in
a timed thread and the resulting speed of rendering was measured.

For each engine a template was created that contained 1) a string
variable ('hello world') 2) iteration over a list (range(100)) 3) a
random number 4) iteration over a Django model, yielding the
attributes. This template was loaded and rendered using the
appropriate Django context. Time was measured with the timeit module
and only represents the rendering time of the engine.

For this simple test Django did OK, coming in 3rd at the middle of the
pack. Genshi did horribly mostly because it is XML based which does
not conform to the Django design philosophies. The one that was
consistently the best by a noticeable amount was Cheetah.

Here are the average times (in milliseconds) for 100 trials of 5 sets
of measurement.
cheetah 0.827
mako 1.328
django 2.207
myghty 2.712
genshi 8.212

I also used pylab and the chart is available here
http://i239.photobucket.com/albums/ff209/justquick/template_bench.png
Email me if you wish to see the raw csv output or source code for this
test.

These results mean that in some cases Django does not render templates
the fastest. Developers should have the option to use whatever engine
they want for their template system. At the same time it should still
have all the compatible functionality of Django so that the
extensibility of the templatetags and filters can transfer over. I am
currently working on a project like this to adapt the winner (Cheetah)
into a Django compatible templating engine which is available here
http://code.google.com/p/django-cheetahtemplate/.

What are peoples' thoughts on the issue of having a multi engine
template system for Django? Does it violate the design philosophies?
Is it worth trying to make this adaption now?

James Bennett

unread,
Nov 14, 2007, 12:55:23 PM11/14/07
to django...@googlegroups.com
On 11/14/07, justquick <just...@gmail.com> wrote:
> These results mean that in some cases Django does not render templates
> the fastest. Developers should have the option to use whatever engine
> they want for their template system.

And they do ;)

(remember, folks, we're just talking about importing and calling
Python functions here; if you don't like Django's template system,
import and use another one. Easy as pie.)

> At the same time it should still
> have all the compatible functionality of Django so that the
> extensibility of the templatetags and filters can transfer over.

Why not just use the extension mechanism of the system you decide to use?

> What are peoples' thoughts on the issue of having a multi engine
> template system for Django? Does it violate the design philosophies?
> Is it worth trying to make this adaption now?

I personally think that Django should continue to ship the default
template system it already has, and that people who prefer another
template system should simply import and use it; it's not like that's
terribly hard to do, and it solves the problem of needing to come up
with lots of meta-template APIs to try to abstract out all the
differences between them (and, honestly, it's not like you could just
change a setting somewhere and have it magically rewrite all your
templates; if you switch template systems, you're in for a significant
job no matter what).

--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

Marty Alchin

unread,
Nov 14, 2007, 1:18:00 PM11/14/07
to django...@googlegroups.com
I'm generally with James on this, that users are already able to use
whatever they like; after all, it's just Python.

The one potential concern I have is, what about generic views? As far
as I can tell, if you want to change template systems, you'd have to
abandon the existing generic views. Either just go with custom views
or rewrite the existing ones to use the new engine, but the shipped
ones become useless.

Of course, I don't really see that as a bad thing, since I don't plan
on switching template engines, but it's at least a bigger problem than
just importing your own in your custom views. That said, if speed is
really that big of a concern, most sites can safely cache the rendered
output and avoid the overhead of the template engine *and* all the
database queries.

And if you need that speed and you *can't* cache the output (live data
view, for example), then you're probably in a special enough case that
it's worth abandoning generic views anyway, since custom views could
be written to work a lot faster than generic ones.

-Gul

justquick

unread,
Nov 14, 2007, 1:26:26 PM11/14/07
to Django users
I am not talking about replacing the whole builtin template system so
that framework wide requires changes. Django is the default rendering
system, but others should be enabled. Django should continue to ship
its template system, which is a great system and has loads practical
tools for web design. I am learning to like it despite the fact that I
learned Cheetah first. But Django should also have the easy option of
using another system, even if it does not have to enable them by
default. At the very least I am interested in doing this on my sites
and will want to further investigate the differences in usage and
performance of these engines in a Django environment. I will implement
what I am proposing which is not meta-template API based, but instead
a set of replacements to the Template class and render_to_response
shortcut. Each engine will require its own particular syntax for
rendering, since the APIs are slightly different among them. As far as
integrating them into the main trunk? Not so sure now, still trying
to think of the best way to easily allow authors access to the
component replacements. Of course you can always just import the
engine in your views and template away from there; these changes I am
making are merely an easy way to integrate Django's template loaders
and contexts with the other rendering engines. The end goal is not to
have to muck with steps like:

from django.template.loaders import find_template_source
import engine module
response = HttpResponse()
template = template(find_template_source('index.tmpl')[0])
template.render(context, out_file=response)
return response

Instead that all would become:

return render_to_response('index.tmpl', context, engine='cheetah')

See? Much nicer, no mucking with template loaders, search directories,
or rendering

Russell Keith-Magee

unread,
Nov 15, 2007, 6:35:36 AM11/15/07
to django...@googlegroups.com
On 11/15/07, justquick <just...@gmail.com> wrote:
>
> from django.template.loaders import find_template_source
> import engine module
> response = HttpResponse()
> template = template(find_template_source('index.tmpl')[0])
> template.render(context, out_file=response)
> return response
>
> Instead that all would become:
>
> return render_to_response('index.tmpl', context, engine='cheetah')
>
> See? Much nicer, no mucking with template loaders, search directories,
> or rendering

I can see what you're trying to achieve here, but I don't think it's
the right solution to the problem. Using this approach, you will need
to remember to put "engine='cheetah'" into every render_to_response
that you use. That creates an API that is just asking to turn into an
annoying bug.

A better approach would be to write your own render_to_response that
encapsulates your template engine of choice. That way, you replace:

from django.shortcuts import render_to_response

with:

from cheetah.django_shortcuts import render_to_response

(or some such code), and all the rendering for an entire module is converted.

render_to_response is a 3 line method, so there's not like there's a
whole lot of overhead in this duplication. I would suggest that if you
are keen on an alternate template engine, you should look at providing
a parallel set of shortcut/utility services, rather than trying to
parameterize the Django shortcuts.

Yours,
Russ Magee %-)

Reply all
Reply to author
Forward
0 new messages