471,083 Members | 1,073 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,083 software developers and data experts.

Using a decorator for generic html templates

Hello all,

While studying some of the templating systems available for Python,
I've come up with an idea to implement templates using decorators. The
following code snippet runs in Python 2.3; a few 2.4 only extensions
are shown as comments. Please note that I have shamelessly copied the
trim function from PEP 257, because it's needed to have the strings
properly formatted.

# HTML templating decorator
# Carlos Ribeiro
# ca********@gmail.com
# http://pythonnotes.blogspot.com

import sys

def trim(docstring):
# shamelessly taken from PEP 257:
# http://www.python.org/peps/pep-0257.html
if not docstring:
return ''
# Convert tabs to spaces (following the normal Python rules)
# and split into a list of lines:
lines = docstring.expandtabs().splitlines()
# Determine minimum indentation (first line doesn't count):
indent = sys.maxint
for line in lines[1:]:
stripped = line.lstrip()
if stripped:
indent = min(indent, len(line) - len(stripped))
# Remove indentation (first line is special):
trimmed = [lines[0].strip()]
if indent < sys.maxint:
for line in lines[1:]:
# Strip off trailing and leading blank lines:
while trimmed and not trimmed[-1]:
while trimmed and not trimmed[0]:
# Return a single string:
return '\n'.join(trimmed)

def raw_html_template(func):
Transforms a simple raw html template function into a function that
returns the __doc__ string. Non-significant spaces are removed,
making the resulting output indent correctly.
def new_func(args):
return func.__doc__

#new_func.func_name = func.func_name # 2.4 only
return new_func

class Root:
#@raw_html_template # 2.4 only
def index(self):
<h1>Hello World!</h1>

index = raw_html_template(index) #2.3 only

A simple test run is:
r = Root()
r.index() '\n <html>\n <body>\n <h1>Hello
World!</h1>\n </body>\n </html>\n '

Comments about this technique:

1) It abuses the doc string to obtain the desired effect. While some
may not like it as a hack, it's actually very clean; the resulting
code looks really nice without extra clutter.

2) More advanced decorators can be supported. For example, embedded
tags can be pre-processed by the decorator, either at "decorating
time" (when the decorator function is run) or at runtime (by means of
special code in the decorated function).

3) Methods that interleave Python code and raw HTML code are *much*
more difficult to handle. I don't have enough knowledge to deem them
impossible, but that's my best guess now. *If* someone is brave enough
to try it, my guess is that it has to rely very heavily on
introspection and low-level disassembly hacks. Not for the faint of
heart... and too [asm|C|INTERCAL]-ish for my taste :-)

4) Another approach that could be possibly taken is to use a metaclass
to control the decoration of all methods that have only docstrings and
no code. Using introspection, the constructor could check all methods
and decorate the ones that need it, building the new object

5) In real world applications, performance may be a concern. I don't
know if the decorator is applied every time a new object instance is
created, or if a caching mechanism of some type is used. If the
decorator is run everytime a new instance is about to be created, then
a different approach is needed, because many web application
frameworks rely on short lived objects to represent stuff such as
actual page handlers. That's where a metaclass approach could be more

6) Last, I don't know if the trim() function is available through some
of the standard libraries, and I have no idea upon where to look after
it. But it would be a good idea to call the standard implementation
instead of repeating the code here. (btw, the implementation has a
small bug: it leaves some extra space at the last line that should be
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: ca********@gmail.com
mail: ca********@yahoo.com
Jul 18 '05 #1
0 1284

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by Ville Vainio | last post: by
4 posts views Thread by Pat Turner | last post: by
7 posts views Thread by Allan Bruce | last post: by
1 post views Thread by Einar HÝst | last post: by
9 posts views Thread by Tyno Gendo | last post: by
2 posts views Thread by Joe Strout | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.