[Web-SIG] Standardized template API
Phillip J. Eby
pje at telecommunity.com
Wed Feb 1 01:43:25 CET 2006
At 05:01 PM 1/31/2006 -0600, Ian Bicking wrote:
>Phillip J. Eby wrote:
>>At 02:03 PM 1/31/2006 -0500, Clark C. Evans wrote:
>>>I'd stick with the notion of a "template_name" that is neither the
>>>template file nor the template body. Then you'd want a template factory
>>>method that takes the name and produces the template body (complied if
>>>necessary). This needs to be once indirect since a template may refer
>>>to other sub-templates. This way your template could be stored
>>>in-memory, on-disk, or in a database, or even remotely using an HTTP
>>>cashe. The actual storage mechanism for the template source code should
>>>not be part of this interface.
>>I'd go even further than this, to note that frameworks need to be able to
>>cache "compiled" versions of templates. The template "engine" should be
>>able to return a "compiled" template that the framework can use to do
>>rendering in future.
>The plugin instance itself can manage the caching. I believe current
>implementations do that (at least TurboCheetah does). Is there anything
>the framework can do for caching that the plugin instance can't?
The plugin doesn't know how long to retain a compiled template if it's
referenced only via strings. If the plugin returns a compiled template
object, then the framework can either hold onto it, or not.
>>Note too that frameworks such as Zope 3 and peak.web have concepts like
>>localization and "skinning" that require the ability to switch out the
>>actual provider of a named template or "view", and in at least the case
>>of peak.web this can be polymorphic. That is, one "skin" could implement
>>template "foo" using Kid and another one using ZPT. So the name of a
>>template needs to be independent of its implementation language, or the
>>ability to plug in different engines is moot.
>>(Currently, TurboGears embeds the chosen template language in code, which
>>means a deployer can't skin the application effectively.)
>I believe that custom find_template implementations could handle these
>cases. Maybe there also needs to be a relative_to_template_name argument
>to find_template, so that it can resolve template names relative to the
>calling template (so, for instance, you can use relative names to the
>template you inherit from).
I don't want plugins to affect *where* templates are retrieved from, or how
their names are interpreted. A template engine's only job should be to
turn a string or stream into a template object.
What I was proposing we do was establish a common mechanism for finding
templates and other resources, taking into account i18n, skinning,
polymorphism, and eggs. That would have a much greater impact on the
Python web world than simply formalizing the Buffet/TurboGears plugin
Indeed, I'd argue that it'd be better here to create a WSGI-based template
interface, rather than a specialized template interface. That is, if the
"compiled template" returned by a template engine is just a WSGI
application object, then it provides a maximum of flexibility. If
individual frameworks want to supply additional data or features, they can
do so via additional environ keys.
Combine that with a resource-locating API, and we'd really be getting
somewhere. The way I see it, a framework would be responsible for creating
locale and skin-layer search lists, and identifying a resource. The API
would be responsible for locating the resource implementations and
returning WSGI application objects.
I don't know if it's politically or technically feasible to actually solve
this, since some template engines bundle a lot of assumptions presently,
like the idea that a template is a Python module or stuff like that. Some
frameworks currently bundle assumptions of their own about such
things. Getting to a workable standard might require some compromises.
On the positive side, relatively few frameworks support the full range of
i18n, skinning, polymorphism, and egg resource options, and so fewer
conflicts are likely the more you get into the high end. For example, Zope
3 supports skins and i18n, but not really eggs and I'm not sure it does
polymorphism. peak.web currently does polymorphism, skins, and eggs, but
doesn't do much w/i18n as yet. Creating a standard would enhance the
capabilities and deployability of *all* participating frameworks, however,
so it seems to me to be worth a go.
The downside, on the other hands, is that since so few frameworks try to
solve the the high-end problems, there's likely to be less widespread
understanding of what the problems are or why you'd want to solve
them. This is the flip side of the issue Jim Fulton pointed out, which is
that people who work at the high end of the problem scale don't see much
benefit in the Turbo/Buffet templating API, because it bakes in way too
many assumptions to allow you to solve any really interesting problems with it.
More information about the Web-SIG