[Web-SIG] Standardized template API
Phillip J. Eby
pje at telecommunity.com
Thu Feb 2 20:49:24 CET 2006
At 01:48 PM 2/2/2006 -0500, Michael Bayer wrote:
>Can those of us who
>have worked less with "the high end" see some real examples of what
>they need, and how they will be marginalized by a template adapter
Have you ever used PHP? ASP? DTML? Specifically, have you ever used them
to generate any content-type other than HTML? This is a trivial example of
a use case that a vars'n'strings approach doesn't support, without
basically reinventing a new protocol that duplicates WSGI.
I totally understand that for the frameworks where the current
vars'n'strings proposal originated, this is a non-issue because they always
have Python code between the framework and the template. But there are
plenty of frameworks (and templating engines) where what you want is to
*just have a template* in order to implement a URL, either as a method of a
published object, or just as an "active page".
The vars'n'strings approach can't do active pages, the WSGI approach can.
>Should those of us concerned about WSGI maybe try out a WSGI- centric idea
>and see how that goes ? Even though I am skeptical of
>it, I've hardly any concept of what it would even look like.
For frameworks like TurboGears that treat a template as a formatter of the
return value of some Python code, the difference wouldn't be
user-visible. And for frameworks, servers, or tools that use WSGI
internally now (e.g. Paste, Routes, maybe Pylons?) there might not be any
implementation to do at all, except to add support for loading/compiling
resources. These tools can already run WSGI apps, they just need support
to allow mapping URLs to templates.
Tools that don't do WSGI yet internally would have to add a WSGI "server"
component that creates an environ dict and add a start_response/write/iter
facility. These aren't that complex, and if the framework is itself a WSGI
application, it can simply pass through a modified version of the 'environ'
it received from the original WSGI server, along with the 'start_response'
it received. It then has to simply return the template's return value to
the WSGI server. In short, the framework just has to act like WSGI
middleware. A trivial example:
def framework_app(environ, start_response):
# framework-specific code to parse environ and figure out
# where the URL points to, updating SCRIPT_NAME and
# PATH_INFO as it goes, so SCRIPT_NAME points to the template
# when done, while adding any framework-specific variables to
# framework-specific code to figure out what template
# engine the template uses
# ask the engine to load a WSGI app from a file
# (or wherever)
app = engine.compile_stream(open(filename,'r'))
# Run the app against the original environ/start response
# and return its return value, unless the framework needs to
# alter the output some way (in which case it should do normal
# WSGI middleware stuff).
return app(environ, start_response)
Now, if you compare this to what you have in the case of vars'n'strings,
you'll notice that one thing this code is *missing* is the code to set a
default content type, status, etc., while dumping out the "string". In the
WSGI approach, that code moves to the *template* side of the fence. If the
framework needs to add or modify headers, it can do so by passing in an
altered start_response, e.g.:
# framework-specific code here to munge headers
return start_response(munged_status, munged_headers)
Does this put more burden on framework developers? Probably so. It will
be the most burdensome for frameworks that don't carry WSGI deep inside
themselves, or whose APIs don't provide any way to do the things WSGI
allows. They may have to write code that recreates WSGI from an internal
request or response object, possibly containing already-parsed form data
and cookies and such. Or, they may simply need to move their traversal or
routing logic nearer to their WSGI input, so that any framework-specific
request/response objects are created "just in time".
Does this put any significant burden on template developers? Probably
not. The most trivial template wrapper would consist of something like:
def trivial_template_app(environ, start_response):
output = ["some %(someVar)s text" % environ['wti.source']]
start_response("200 OK", [('Content-type','text/html')])
Templating tools are then in a position to offer response-management API
directly. For example, a ZPT wrapper could offer Zope-style
REQUEST/RESPONSE objects for use in the template, because it would be
dealing with WSGI.
The single strongest argument that I think can be made *against* the WSGI
approach is quite simply that I'm asking framework developers to help make
their frameworks obsolete, by moving their request and response objects to
the periphery of their frameworks, so that developers have not only a
choice of template *syntax*, but also a choice of request/response APIs
associated with those templates.
Perhaps that's an unrealistic idea; maybe it's too soon to push for WSGI
adoption phase 2 (the de-frameworkification of the frameworks). Maybe the
only realistic consensus at this point in time is a niche API for
vars'n'strings. Maybe the only way to showcase the power of what I'm
proposing is to make WSGI wrappers for some template engines and implement
the load/compile/save API I proposed on some server-side stuff. I just
don't want to end up in the position of having spent time to write Yet
Another Framework, as opposed to contributing code to a common standard.
More information about the Web-SIG