Registered: Jan, 2006
Re: Django vs. Cheetah: 1-0
Posted: Feb 1, 2006 12:33 AM
> 100,000+ lines of .asp or .jsp
ouch! I'm sorry of the pain you suffered :)
I understand where you're coming from but think we're miscommunicating on a few points.
First, Cheetah is being used very successfully on projects of a similarly large scale with very diverse teams: http://cheetahtemplate.org/whouses.html. IronPort has over a million lines of Python and Cheetah code. If I understand correctly, >100,000 lines of that is Cheetah code. I personally manage a project with roughly 200,000 lines of Python and Cheetah code. These teams aren't tolerating "a lot of rough edges" or "jumping through some hoops to get things done." They're raving about it: http://cheetahtemplate.org/praise.html.
They're not grumbling about Cheetah compiling into Python classes. That is one of the key features they rave about:
"We have found Cheetah to be a gloriously flexible and powerful technology. Functions within templates allowed us to do far more elegant structured programming at the document level. Being able to use templates as python classes, importing constants and other goodies directly from our middleware python code really lets them act as first class code members instead of an ugly lesser citizen.
- James Robinson (socialserve.com)
The security hole argument is completely valid with regards to Cheetah 1.0. (Are django templates completely sandboxed?)
However, Cheetah 2.0 is a very different beast. It allows you to define a smaller subset of the language when you need to restrict what certain developers/designers can put in their templates. The subset can be as small as you want. You can have developers with higher privileges create a template using the full unrestricted syntax and then have less privileged developers create a specialized subclass of that same template using only a restricted subset of the syntax.
Here's a trivial example (~10 lines) of how to create a subset that has no directives and allows only a few specific placeholders
from Cheetah.Template import Template
from Cheetah.Parser import ForbiddenExpression
def filterExpr(parser, expr, exprType, rawExpr, startPos=None):
if rawExpr not in ('$a','$b','$c', '$f("Y")', '$f', '$f()'):
if startPos is not None:
raise ForbiddenExpression(parser, '%r is not a permitted expression'%rawExpr)
_CHEETAH_compilerSettings = dict(
safeSrc = '''
$a $b $c $f $f() $f("Y")
unsafeSrc = '''
$a $b $c $f $f() $f("Y")
#def method(x, y)
unsafeSrc2 = '''
Unsafe source 2
$a $b $c $d $f $f() $f("Y")
unsafeSrc3 = '''
Unsafe source 3
$a $b $c $f $f() $f("Y") $f("N")
searchList = [dict(a='Y', b='Y', c='Y', d='N', f=func)]
for src in (safeSrc, unsafeSrc, unsafeSrc2, unsafeSrc3):
print 'Normal Template Class:'
print 'Safe Template Class:'
The 'unsafe' ones raise some like this:
'f("N")' is not a permitted expression. Line 3, column 26
2 |Unsafe source 3
3 |$a $b $c $f $f() $f("Y") $f("N")
See if you can slip something by that.
If you'd rather have unsafe code just printed in the output rather than raise ForbiddenExpression there is a simple mechanism for doing that as well.
> BTW, your example with CMS and Wiki is a good one too, but
> there are some ways around it like filtering input, or
> (you saw it coming, right?) using a simpler template
I agree about using a simpler template language for such things, which is exactly what Cheetah's filters allow you to create.