The Artima Developer Community
Sponsored Link

Weblogs Forum
Django vs. Cheetah: 1-0

86 replies on 6 pages. Most recent reply: Jan 27, 2008 10:34 PM by Johnny Stovall

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 86 replies on 6 pages [ « | 1 ... 2 3 4 5 6 | » ]
has

Posts: 15
Nickname: has
Registered: Nov, 2004

Re: Django vs. Cheetah: 1-0 Posted: Feb 1, 2006 1:59 PM
Reply to this message Reply
Advertisement
> An interesting option for templating is Chris McDonough's
> Meld3:
> http://www.plope.com/software/meld3

Yeah, DOM-style templating systems are sweet. In a similar vein (self-link):

http://freespace.virgin.net/hamish.sanderson/htmltemplate.html

It's mature, well-documented and a good performer, and pretty liberal as to the sort of markup you can feed it. Extensibility isn't quite up to scratch (I didn't really consider the metaprogramming possibilities till after the API freeze), though there is an unreleased experimental fork that addresses that.

...

A good comparison is to the View and Controller layers in Apple-style MVC.

In Apple MVC, the View layer consists solely of graphical widget objects, assembled live and stored in serialized form (.nib) using Interface Builder, and the Controller layer contains the glue code that pulls data from the Model layer and inserts it into the View objects.

With DOM-style templating engines, the tagged HTML file is analogous to the .nib file, the templating engine = the AppKit framework that turns this data back into live objects, and the Python code that manipulates these objects = the Controller layer.

...

The advantages of DOM-style templating engines:

- Quick to learn, trivial to maintain due to small and simple implementation, API and documentation, and no custom mini-languages to learn.

- Powerful, flexible and extensible, since the host language is used for all display logic. (This also avoids the tendency for endless feature creep.)

- Complete separation of presentation logic from markup, so much more amenable to workflows where design and programming are handled by different people than code-in-markup or markup-in-code approaches.

- No Greenspun's Tenth Rule issues. Honestly, with a powerful, mature and very well-known language like Python available, I think folk have to be mad inventing all sorts of weird and wonderful custom mini-languages instead of just levering what's already available. (Although this last one isn't totally unique to DOM-style systems: there are one or two macro-style engines that use Python, e.g. Spyce.)

Downsides:

- Not as 'familiar' or well-known as macro-style systems; blame PHP and ASP for being first through the door, resulting in a greater historical inertia behind the latter.

- A bit more abstract than the embedded-code-in-markup approach since you're dealing with an object model, so requires at least a modicum of programming knowledge and skills to handle the coding side.

- Not quite as fast at rendering output (assuming similar degree of performance optimisation), since the more dynamic approach means higher overheads due to the greater amount of object creation/destruction and method dispatch.

That all said, IMO neither of the first two are big issues since:

1. You don't beat the pack by slavishly imitating what they're already doing but by getting the jump on them. (Macro-style templating is soooo 20th century...)

2. The code-markup separation removes the need for graphic designers to muddle through the coding side as well. Besides, the slightly higher programming skills required are nothing that 99% of Python users shouldn't already possess, and more than offset by the minimal learning curve and ability to leverage all their existing Python knowledge directly.

Whether the performance difference is an issue or not will depend on individual circumstances. While there may be a 2-3x difference in rendering speed, HTML rendering is only one small part of the overall web application and chances are that in many apps the major performance bottlenecks will be in other areas. And if performance really is that critical then folk ought to be working in C++, not Python, anyway.

...

BTW, if you _really_ wanted to provide a basic macro-style templating language for complete noobs' benefit, it should be relatively trivial to write one that compiles simple custom-code-in-markup templates into markup and code for a DOM-style engine. This would provide novice users with excellent future-proofing since they can start off using the macro engine for simple stuff then drop into the DOM-style system once they outgrow it, rather than constantly begging for extra features to be added to the formerly-simple macro engine or having to throw away all their existing template work and start all over again in YAPTL.

...

HTH

p.s. For non-HTML templating, see texttemplate <http://freespace.virgin.net/hamish.sanderson/texttemplate.html>. (No need for a big complex one-size-fits-everything system when they're both so darn simple in the first place.)

Eugene Lazutkin

Posts: 15
Nickname: elazutkin
Registered: Jan, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 1, 2006 9:34 PM
Reply to this message Reply
> Here's a trivial example (~10 lines) of how to create a
> subset that has no directives and allows only a few
> specific placeholders

I cannot say I am crazy about the code in your example, but your post changed my perception of Cheetah making it more positive. I will definitely check out Cheetah 2.0. I wish all "Use My Stuff" promoters were like you: less emotions, and more examples proving your point of view.

> > 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
> > language.
>
> I agree about using a simpler template language for such
> things, which is exactly what Cheetah's filters allow you
> to create.

Frankly I was thinking more about ReST, Wiki and similar markup. When I deal with non-programmers (e.g., general public, or designers) I prefer declarative over imperative style.

Thanks,

Eugene

Tavis Rudd

Posts: 13
Nickname: tavis
Registered: Jan, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 2, 2006 12:48 AM
Reply to this message Reply
> I cannot say I am crazy about the code in your example,
> but your post changed my perception of Cheetah making it
> more positive.
it's just a quick and filthy example ;)

> I will definitely check out Cheetah 2.0. I
> wish all "Use My Stuff" promoters were like you: less
> emotions, and more examples proving your point of view.
hehe, thanks.

> > > BTW, your example with CMS and Wiki is a good one
...
> Frankly I was thinking more about ReST, Wiki and similar
> markup. When I deal with non-programmers (e.g., general
> public, or designers) I prefer declarative over imperative
> style.
Ah, I see your point now. I agree completely. Declarative / doc-structure-oriented languages are better for that. I'm using Textile, with restricted-Cheetah for simple $variable interpolation, for a wiki system I run. This is actually what spurred me to write the filtering stuff. We exposed ReST to end-users for page editing in another project, but unfortunately its linking and image syntax confused everyone, including me. ReST is great for inline code documentation. It's not suitable for wikis, IMHO.

William Dodé

Posts: 2
Nickname: wilk
Registered: Jan, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 2, 2006 6:41 AM
Reply to this message Reply
Thanks to remind us that Textile (and pytextile) is the best companion to cheetah that demonstrate that we can do html without the pain of XML.

A list ?

>>> from textile import textile
>>> from Cheetah.Template import Template
>>> t = Template("""
... #for $i in range($z)
... * i = $i
... #end for
... """)
>>> t.z = 3
>>> print textile(str(t))
<ul>
<li>i = 0</li>
<li>i = 1</li>
<li>i = 2</li>
</ul>
>>>

A table ?

>>> t = Template("""
... #for $i in range($z)
... |i=|$i|
... #end for
... """)
>>> t.z = 2
>>> print textile(str(t))
<table>
<tr>
<td>i=</td>
<td>0< ;/td>
</tr>
<tr>
<td>i=</td>
<td>1</td>
</tr>
</table>
>>>

Tavis Rudd

Posts: 13
Nickname: tavis
Registered: Jan, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 2, 2006 10:59 AM
Reply to this message Reply
You can also do it like this:

>>> from Cheetah.Template import Template
>>> t = Template("""
... #from textile import textile
... #call textile
... #for $i in range(20)
... * i = $i
... #end for
... #end call
... """)
>>> print t
<ul>
<li>i = 0</li>
<li>i = 1</li>
<li>i = 2</li>
</ul>
>>>


And you could even do something like this (using some metaclass like magic to add cheetah capabilities to textile):


>>> from Cheetah.Template import Template
>>> from textile import Textiler
>>> class TemplTextile(Textiler):
>>> def __init__(self, namespaces=None):
>>> self._initCheetahInstance(namespaces=namespaces)
>>> Textiler.__init__(self, text=str(self))
>>> tclass = Template.compile(baseclass=TemplTextile, source="""
... #for $i in range($x)
... * i = $i
... #end for
... """)
>>> print tclass({'x':3})
<ul>
<li>i = 0</li>
<li>i = 1</li>
<li>i = 2</li>
</ul>
>>>


I haven't tested this 2nd example but it should work.

Note that I'm using a hacked verion of pytextile that doesn't have the ridiculous requirement for list items to be flush on the left column.

Tavis Rudd

Posts: 13
Nickname: tavis
Registered: Jan, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 2, 2006 11:12 AM
Reply to this message Reply
Further to that last example
...

>>> t2 = tclass.subclass("""
... #for $i in range($z)
... |i=|$i|
... #end for
... """)
>>> print t2({'z':3})
<table>
<tr>
<td>i=</td>
<td>0< ;/td>
</tr>
<tr>
<td>i=</td>
<td>1</td>
</tr>
</table>
>>>

Tavis Rudd

Posts: 13
Nickname: tavis
Registered: Jan, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 2, 2006 11:35 AM
Reply to this message Reply
this blog system appears to be mucking with the html inside pre ... /pre blocks. let me try that again (ignore and random semi-colons it inserts):


>>> t2 = tclass.subclass("""
... #for $i in range($z)
... |i=|$i|
... #end for
... """)
>>> print t2({'z':3})
<table>
<tr>
<td>i=</td>
<td>0</td >
</tr>
<tr>
<td>i=</td>
<td>1</td>
</ tr>
<tr>
<td>i=</td>
<td>2</td>
</tr>
< ;/table>
>>>

Ben Bangert

Posts: 6
Nickname: bbangert
Registered: Jan, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 2, 2006 3:46 PM
Reply to this message Reply
While Pylons uses Myghty by default, it utilizes template plug-in's to provide Cheetah, Kid, STAN, or whatever other template language (supporting template plug-ins) you'd like to use.

As for actual template languages, I really like everything I've seen about Django templates, and as they're split into their own package have offered to contribute time and effort so that they support whatever template plug-in standard is agreed on.

Template languages are a very very personal matter, people have very strong love/hate feelings towards them. I've used a variety myself, and now have a hard time leaving the powerful features Myghty affords me. I've covered them in depth in a blog posting: http://www.groovie.org/articles/2005/10/18/hooked-on-myghty

Since Myghty lets you use full Python syntax, it's not necessarily safe if you want to let web users edit templates. It's this reason that I'm interested in using Django templates as well, so I can more narrowly define what the template should be allowed to do in un-trusted situations.

While I'm not personally big on XML style templating like Kid or TAL, other people enjoy it and are productive. I'd really really hate it if the result of Guido coming in swinging the template axe was that we had less choice of templating languages. Choice is good, Cheetah, Myghty, Django templates, Kid, and others provide choices that we should value, not destroy.

Jeff Hinrichs

Posts: 2
Nickname: dundeemt
Registered: Feb, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 3, 2006 8:34 PM
Reply to this message Reply
In the article, Guido gives an example of the two templating languages.

#if $name
<h1>Hello $name</h1>
#else
<h1.Hello there</h1>
#end if

This is written in Django as:

{%if name%}
<h1>Hello {{name}}</h1>
{%else%}
<h1>Hello There</h1>
{%endif%}


I believe that application logic within the templating system is a very, very bad idea. First off, if used at all the templating "language" should be the same as the application. I don't want another language -- especially such horrid looking ones, as a part of my system. Web apps are primarily, MVC anyway. Why use a stinky, one-off, language for your viewer code? My preferred way is akin to:

<..controller snippet..>
if not name:
name = "There"
Template.add(name)
Template.publish()
----------------------------
< ..template snippet...>
<h1>Hello {{name}}</h1>


The app logic stays where it belongs, in the controller not the viewer. I've got enough going on in the viewer with AJAX and javascript, et al.

The other problem, with too smart by half templating languages is that they are unworkable if you have designers (read not programmers) on your web-team. The IF-THEN shown in the original blog would cause most visual editing tools to spit up blood and die. However, the code I used as a hypothetical would not.

Just because PHP and ASP like to combine logic and presentation like some fur ball that just grazed a black hole doesn't mean that it is a good thing, nor the right way to go.

Of course, that is just my opinion -- bring your own salt<g>

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Django vs. Cheetah: 1-0 Posted: Feb 3, 2006 9:08 PM
Reply to this message Reply
> I believe that application logic within the templating
> system is a very, very bad idea.

But conditional sections and loops are commonly used for UI logic. An example for conditional text from the Artima site: when an article has one or more user comments, there's a bit of text somewhere saying "There are already <N> comments; why not *add yours*?". But when there are no user comments yet, it says "Be the first to *add a comment*." The part between asterisks links to the add-a-comment form. Doing this in the application logic would be much more tedious while doing it in the template is trivial.

Ditto for loops -- again, a hypothetical example from the Artima site: there's a list of all the comments associated with a blog entry; it's very convenient to be able to express this in the template using a for loop whose body renders one comment.

Have you developed realistic web applications yourself? How did you do these things without conditionals or loops in the template?

Looking at PyMeld, which claims to be completely separating program logic and HTML, I can't help thinking that a lot of what is called "program logic" by the advocates of this separation, is really "UI logic" -- similar to the examples I quoted above.

has

Posts: 15
Nickname: has
Registered: Nov, 2004

Re: Django vs. Cheetah: 1-0 Posted: Feb 3, 2006 10:49 PM
Reply to this message Reply
> > I believe that application logic within the templating
> > system is a very, very bad idea.
>
> But conditional sections and loops are commonly used for
> UI logic.

I think you're both confusing 'application logic' and 'presentation logic'.


> Looking at PyMeld, which claims to be completely
> separating program logic and HTML, I can't help thinking
> that a lot of what is called "program logic" by the
> advocates of this separation, is really "UI logic" --
> similar to the examples I quoted above.

If you see any 'advocates' saying that then they deserve a slap. PyMeld, like other DOM-style systems, physically separates 'presentation logic' from HTML. There's no enforcement of separation between presentation and model logic as some macro-style systems do, but one can fairly assume any programmer who knows MVC will naturally do so regardless of whether it holds their hand or not.

Anyway, I've written more about the philosophy and characteristics of DOM-style templating here:

http://www.artima.com/forums/flat.jsp?forum=106&thread=146647&start=30&msRange=15#190627

and here:

http://www.artima.com/forums/flat.jsp?forum=106&thread=146606&start=60&msRange=15#190597

The comparison to Cocoa programming on OS X is such a good one I even repeated it twice. :) Folk who are used to mixing their presentation logic in with their widget assembling code may find it a bit disconcerting at first given the physical separation between the two, but once the mindset clicks it all feels very natural. Yes you probably end up writing a few more lines of code this way, but if that's a significant worry then you probably want to cut out functions and classes as well and just write the entire program as one nice long uninterrupted routine. ;p

Regarding 'How To Do X/Y/Z' examples, PyMeld is rather thin but HTMLTemplate [self-link] includes tutorials and examples that cover all the basic principles. There's an online example here if you want a quick look:

http://freespace.virgin.net/hamish.sanderson/appscript_examples/iTunes_albums_to_HTML.html

and the package is here:

http://freespace.virgin.net/hamish.sanderson/HTMLTemplate-1.4.1.tar.gz

HTH

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Django vs. Cheetah: 1-0 Posted: Feb 4, 2006 8:00 AM
Reply to this message Reply
> I think you're both confusing 'application logic' and
> 'presentation logic'.

Ah, this makes more sense. The PyMeld advocacy page calls it "program logic" which suggests that the confusion is rather widespread. :-(

Having just half-completed the conversion of one page (about 20%) of my internal Google app to Django templates (no others parts of Django used at this time), I still believe that a DOM-style approach would be much more painful, in part *because* of the separation between HTML and presentation logic.

For example, I am displaying an object with a whole bunch of attributes. I'm still deciding which attributes are relevant to the user. Using Django I can simply add markup with variable references to the template. Generalizing from your itunes example right, I would have to add new markup to the template, and then make a corresponding addition to the presentation logic in Python. This requires more context switching which is one of the major well-known sources of productivity slowdown.

Also, all examples I've seen so far are changing the "content" of an element. However, in my sample app, I frequently have links whose value is (in part) derived from a variable. In Django I can write

<a href="/user/{{username}}">View {{username}}'s info</a>.

How do I do that using your system or PyMeld?

(PS. Unless you want full-bore anonymity, which I doubt since your name appears in some of the URLs you quote, please post using first and last name instead of initials. This makes it easier for me to remember you.)

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Django vs. Cheetah: 1-0 Posted: Feb 4, 2006 8:04 AM
Reply to this message Reply
Correction: I made a simplification on the Python API for Django that happened to work in the simple example but doesn't always work (e.g. it breaks if the template uses a for-loop) and doesn't follow the docs. Instead of

t.render({"name": "Adrian"})

I should have written

t.render(Context({"name": "Adrian"}))

where Context is imported from the same place as Template.

has

Posts: 15
Nickname: has
Registered: Nov, 2004

Re: Django vs. Cheetah: 1-0 Posted: Feb 4, 2006 10:02 AM
Reply to this message Reply
> I still
> believe that a DOM-style approach would be much more
> painful, in part *because* of the separation between HTML
> and presentation logic.

I'll say it now: there will always be some tradeoffs somewhere, whatever you do. Anyone who claims any of these systems is a free lunch is either naive or fibbing.

FWIW though, I originally built a full, working macro-style engine influenced by the classic systems like PHP and ASP, only to trash it a few months later and completely start over by conceiving, designing and implementing a DOM-style engine from first principles. Pretty painful, but no regrets.


> For example, I am displaying an object with a whole bunch
> of attributes. I'm still deciding which attributes are
> relevant to the user. Using Django I can simply add
> markup with variable references to the template.
> Generalizing from your itunes example right, I would have
> e to add new markup to the template, and then make a
> corresponding addition to the presentation logic in
> Python. This requires more context switching which is one
> of the major well-known sources of productivity slowdown.

If you mean you have to switch from one file to another during development more often, then yes. You have the same issue with Cocoa development, bouncing between drag-d-dropping objects in Interface Builder and typing source code in XCode.

The first counter-argument is that separating the two concerns allows you to use the best tools for developing each: Dreamweaver, FrontPage, HTMLTidy, etc. for one; vi, emacs, Eclipse, lint, etc. for the other.

The second is that, in practice, one tends to minimise those expensive context shifts anyway: first marking a whole bunch of template nodes in the HTML editor, then switching to the code editor to fill in the implementation one bit at a time. You can still test each new feature as you go; any template nodes that aren't yet "hooked up" simply don't do anything.

If anything, with a well-designed DOM-style system it should be much easier to test sections of the template in isolation. Your test harness can directly invoke whichever function manipulates the part of the template you're interested in, then render that portion for verification. You can temporarily stub out sections of code without affecting the markup structure.

Therefore, this separation not only allows you to work in your standard Python tools, it also lets you leverage your existing Python skills and techniques as well. The philosophy of reuse extends beyond just the templates themselves.

..

Furthermore, with a sufficiently flexible and introspective API, things can get very interesting: you can create separate libraries of add-on features, stuff like automatic interpolators that take a template node and a Model object and use key-value bindings to insert content automatically. Add-ons like that will reduce the amount of glue code you need to write between Model layer and template DOM for common tasks, improving productivity. And because it's all external add-ons, you're not bloating the original implementation with the increased maintenance costs and longer learning curve that feature creep causes.

BTW, this last bit is what interests me most about DOM-style engines: whereas macro-style territory has pretty much been done to death by now and I doubt there's much new ideas left to be had, the DOM-style approach still looks to offer plenty room for fresh investigation and experimentation. It's got a definite "but give a man a copy of Lisp..." vibe to it.

..

Finally, if you're still concerned that a DOM-style system may present a marketing problem for folks who can't yet handle abstraction or are just too set in their macro-munging ways, bear in mind that it is possible to implement a macro-style interface as a preprocessor on top of a DOM-style engine, both as a deliberately 'low-end' solution in itself and as a 'transitional bridge'. You can't do it the other way though.

...

> Also, all examples I've seen so far are changing the
> "content" of an element. However, in my sample app, I
> frequently have links whose value is (in part) derived
> from a variable. In Django I can write
>
> <a href="/user/{{username}}">View {{username}}'s info</a>.
>
>

> How do I do that using your system or PyMeld?

A few options.

1. You can specify the whole value in the controller code rather than the markup, e.g.:

infoLink.atts['href'] = os.path.join('/user', username)


2. You can insert a 'dummy' element as placeholder, e.g.

<a ...>View <span node="-con:username"/>'s info</a>

or:

<a ...>View <span node="-con:username">Joe Foo</span>'s info</a>

if you want it to add mockup values so it previews nicely. (Appending '-' to the 'con' directive tells the renderer to automatically omit the <span> and </span> tags on output.)


3. You can get the existing content, perform a string interpolation or substitution, then reinsert the result, e.g.:

<a ...>View %s's info</a>

infoLink.content = infoLink.content % username


Or any combination of the above.

HTH

Tavis Rudd

Posts: 13
Nickname: tavis
Registered: Jan, 2006

Re: Django vs. Cheetah: 1-0 Posted: Feb 4, 2006 5:46 PM
Reply to this message Reply
Guido,
you mentioned that you introduced a Python syntax error into a template and it was hard to debug. Do you mind sharing what that error was?

The forthcoming Cheetah release has much better syntax exception reporting for cases where bad Python syntax slips in but the Cheetah parser itself doesn't recognize it as bad syntax. Here's an example:


Traceback (most recent call last):
File "syntaxtest.py", line 4, in ?
print Template("""
File "/usr/lib/python2.4/site-packages/Cheetah/Template.py", line 1251, in __init__
self._compile(source, file, compilerSettings=compilerSettings)
File "/usr/lib/python2.4/site-packages/Cheetah/Template.py", line 1539, in _compile
keepRefToGeneratedCode=True)
File "/usr/lib/python2.4/site-packages/Cheetah/Template.py", line 842, in compile
raise parseError
Cheetah.Parser.ParseError:

Error in the Python code which Cheetah generated for this template:
===================================================================== ===========

invalid syntax (DynamicallyCompiledCheetahTemplate.py, line 83)

Line|Python Code
----|-------------------------------------------------------------
81 |
82 | write('\n\n')
83 | for i an range(10): # generated from line 4, col 1
^
84 | _v = i # '$i' on line 5, col 3
85 | if _v is not None: write(_filter(_v, rawExpr='$i')) # from line 5, col 3.
86 | write('\n')

================================================================== ==============

Here is the corresponding Cheetah code:

Line 4, column 1

Line|Cheetah Code
----|-------------------------------------------------------------
2 |#compiler useNameMapper=False
3 |
4 |#for i an range(10)
^
5 | $i
6 |#end for
7 |







Here's another example where Cheetah's parser itself catches the bad syntax (Cheetah 1.0 does this):


Cheetah.Parser.ParseError:

Invalid end directive
Line 6, column 6

Line|Cheetah Code
----|-------------------------------------------------------------
3 |
4 |#for i in range(10)
5 | $i
6 |#end fo
^
7 |
8 |
9 |

Flat View: This topic has 86 replies on 6 pages [ « | 2  3  4  5  6 | » ]
Topic: Django vs. Cheetah: 1-0 Previous Topic   Next Topic Topic: ScalaTest 0.9 Released

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use