[Web-SIG] A trivial template API counter-proposal

Guido van Rossum guido at python.org
Sun Feb 5 19:40:38 CET 2006

> >  Or static HTML pages that are written
> >to the filesystem and then served by a classic Apache setup? Or source
> >code (program generators are fun toys!)?

> Use the output file's write() method as the "write" callback returned by
> start_response(), or use one of the wsgiref handlers that you give
> arbitrary file-like objects to.

I didn't see an output file in the proposed standard. All I saw was a
WSGI interface. The output file is a figment of your implementation.

> >ISTM that a template that does anything besides producing the
> >*content* of a download would be a rather extreme exception -- e.g.
> >the decision to generate a redirect feels like *application* logic,
> >while templates ought to limit themselves to *presentation* logic,
> Not every framework developer agrees with you on this point; some
> explicitly eschew the separation of presentation and application, although
> I personally tend to agree with you.  In the absence of BDFL pronouncement
> on which frameworks are "right" or "wrong", my policy has been to advocate
> framework neutrality - to the extent I'm able to identify and get past my
> own biases, of course.

It is my strong preference that the standard API we are attempting to
design here does *not* tie you strongly to WSGI or the generation of
dynamic web content.

> For ASP/PHP-style frameworks, it's routine for the "template" to make these
> kinds of response-control decisions, and it's certainly seen a lot in Zope
> 2 applications using DTML as well.  Even if only for backward
> compatibility, it seems wrong to me to leave all these applications unable
> to operate under the new standard.

There's nothing wrong with having some things that can invoked from
the template that set or add headers behind your back, if the template
engine supports such a thing. But I think the API to let it do so
might not be part of the standard, or it might be an optional part of
the standard; I want to be able to use a templating engine in a
non-web context and still use it (of course I won't be able to set
headers then, but I'd assume this functionality is optional and I can
just elect not to use it).

> (Also, even in frameworks where logic and presentation are kept separate,
> it doesn't necessarily mean that a template doesn't still need to control
> its content-type, or that code invoked from the template in order to access
> data may not result in data being added to the response headers.  In Zope
> 3, a "view" can do such things, as might components rendered in the view.)

I'm okay if the proposed standard doesn't provide access to every
aspect of Zope 3 templates. If I were intereste in using the
web-specific features of Zope3 templates, I should probably be using
Zope 3.

> >and
> >for that, an API that produces a string or writes to a stream seems to
> >make more sense. What am I missing? Are you proposing that I should
> >fake out the wsgi API and capture the strings passed to write() and
> >the sequence returned?
> In that case, why don't you just use the template engine directly?

Because every template engine has a @#$%! different API!!!!

The whole *point* of asking for a standard template API was to reduce
the effort needed to switch template engines. I realize that I still
need to rewrite my templates to conform to the new template syntax,
and I may need to provide my context in a different form because not
all templating engines have the same power of reaching into objects to
extract information. But I still see the different template APIs as an
unnecessary barrier to switching. Even if I'm not switching within one
project, I may have to maintain two projects that use different
templating engines. Like the DB-API standard, having analogous APIs

> But I
> don't see how such an API is a *web* templating API in that
> case.  Shouldn't such things just follow the stdlib string template
> API?  Why do we need a *web* standard for string templating?

I didn't ask for a *web* templating API; I suspect you've been reading
too much into my request. I specifically asked for a *standard
templating API*. Note that both Cheetah and Django templates *have*
such an API, and provide examples of how to use them -- the grating
part is that they are gratuitously *different*.

> As for capturing the output, it's pretty trivial to do if for some reason
> you have to:
>       handler = BaseCGIHandler(StringIO(""),StringIO(),StringIO(),environ)
>       handler.run(app)
>       output = handler.stdout.getvalue().split('\r\n\r\n',1)[1]

This assumes wegiref though. I'd rather not make wsgiref a required
part of the standard.

> This could probably be added as a utility function to wsgiref, or perhaps a
> simpler and more efficient form thereof.

No, I'd like to see the templating API and WSGI completely decoupled,
except for an optional part where in the evaluation context passed
into a template at render time, you pass in an object that lets the
template manipulate headers etc.  It would be fine if the latter used
WSGI somehow. But there *must* be a standard way yo invoke the
template engine (context in, string or stream out) without assuming
it's an HTTP response.

> By contrast, to allow response-manipulating templates with a non-web API,
> there would have to be some way to provide WSGI or a WSGI-like API
> thereto.  So far, nobody has proposed a way of doing that to be included in
> the templating standard.  Ian has suggested that one could stick some API
> functions in the variables passed to the template, but hasn't proposed a
> standard for doing so.  My counterproposal is that since WSGI already
> exists, it isn't necessary to create an entirely new standard for same.

Well, I don't like it. :-(

> Currently, the progress of the discussion I've been having with Ben Bangert
> is that we would split the templating API into two or three layers.  The
> layer I'm describing now would be part of "WSGI Linking" and the kind of
> API you're describing would be an optional extension to "WSGI
> Embedding".  Since not all template systems can reasonably be used without
> access to a request/response, it seems to me that the string-only facility
> should be considered an optional extension.

How can it be considered a templating system if it doesn't have access
to a request/response? Surely somewhere in the bowels is an engine
that renders a template in a context to a text stream. The rest ought
to be considered part of the web framework that hots the templating
engine. ISTM we may be confused (or simply disagreeing) about the
boundary between the templating engine and the framework.

> While it means that there will be at least three different parts to the
> spec, it will hopefully be clearer what different frameworks and templates
> do and don't do with regard to using each other's templates or vice versa.

Please keep coming up with proposals and rationales for them. I will
certainly admit that I haven't used a Python web framework in a while
(not since I left Zope :-). But when I see Cheetah and Django and some
competitors that were mentioned in responses to my blogs, a certain
"Platonic ideal" of a templating engine emerges in my brain, and I'd
like at least the API for that standardardized, if at all possible, so
people writing frameworks can choose from the many templating engines
available, and people with templating needs *outside* a web context
can have the same selection.

> > > >(PS having tried WSGI a bit now I'm fine with it.
> > >
> > > WSGI - it's no worse than a trip to East Berlin.  :)
> >
> >Well, it *is* quite a trip to memory lane... Intellectually I
> >understand that the CGI feel is simply practical; but emotionally,
> >using environ["PATH_INFO"] feels like a big step back compared to
> >request.path.
> The idea of course was to allow existing framework APIs to wrap WSGI, so
> that you can have request.path or REQUEST.path_info or whatever suits your
> fancy.  It was never intended that anybody but framework developers write
> "bare metal" WSGI code, and such developers have to touch either CGI or
> HTTP in their code anyway.

Yeah, but potentially this causes several translations of the data
(especially since WSGI requires a *real* dict, not something with
mapping behavior) if the server's native API doesn't come in he form
of CGI-compatible environment variables. This seems counter to the
desire for it to be fast.

--Guido van Rossum (home page: http://www.python.org/~guido/)

More information about the Web-SIG mailing list