qp
Integrating Evoque Templating with the
QP Web Framework
is pretty straightforward. As an explanation, here's the echo
demo site, included in the QP distribution, modified to use Evoque.
The changes are probably self-explanatory, but for the record
here's a commentary on each one:
- First of all
slash.qpyis renamed toslash.pyas the source code is now 100% python. - We import (first 2 import lines) what we need to be able to
set up an Evoque
domain. - The functions
qp.pub.common.headerandqp.pub.common.footerare no longer needed, so are not imported. Instead, we do importqp.pub.common.page, and the template used for each page rendering will take care of its own header and footer. - We override
Publisher.__init__()to be able to set up an Evoquedomainfor the site, via the separately specifiedset_domain()method.-
We designate the
evoque/sub-folder as root for our default template collection, but this can be anywhere on the file system. We may of course also specify other collections. -
We extend the evaluation global namespace as we need to,
here we only will need the
pformatutility. - We set a template under a name that we will use as default.
-
We designate the
- We override
Publisher.page()so that it knows how to get and evoque a template. Note that thepage()API remains identical -- except for the added optionaltemplatekeyword by which an export may select which template to use. If notemplatekeyword is specified onpage()then the default template name is used. - We migrate the presentation code from
SiteDirectory.index()to theitems.htmltemplate. We also tell theindex()method to use theitems.htmltemplate. - Just for the heck of it, we also make
items.htmlanoverlay, overriding only thecontentsub-template, on top ofbase.html-- that takes over the functionality of theheader()andfooter()QP functions while also offering additional flexibility, e.g. may have as many base templates as desired, or a base template can be more complex than just to handle a header and a footer.
The code - slash.py
import sys
from os.path import join, dirname, abspath
import logging
from evoque.domain import Domain
from qp.pub.publish import Publisher
from qp.pub.common import get_request, page
from qp.fill.directory import Directory
from pprint import pformat
class SitePublisher(Publisher):
configuration = dict(
http_address=('', 8001),
as_https_address=('localhost', 9001),
https_address=('localhost', 10001),
scgi_address=('localhost', 11001),
)
def __init__(self, **kwargs):
super(SitePublisher, self).__init__(**kwargs)
self.set_domain()
def set_domain(self):
default_dir = abspath(join(dirname(__file__), 'evoque'))
# create template domain instance
# here restating all defaults, for doc convenience
self.domain = Domain(default_dir,
restricted=False, errors=3, log=logging.getLogger("evoque"),
cache_size=0, auto_reload=60, slurpy_directives=True,
quoting="xml", input_encoding="utf-8", filters=[]
)
# extensions to global namespace
self.domain.set_on_globals("pformat", pformat)
# preload a default template, e.g. for error pages
self.domain.get_collection().get_template("", "base.html")
# other setup e.g. adding other collections, template aliases
# see: http://evoque.gizmojo.org/usage/
def page(self, title, *content, **kwargs):
"""(title, *content, **kwargs) -> h8
Return a page formatted according to the site-standard.
"""
# we make use of only the "template" kwarg -- there are
# other possibilities, see: domain.get_template()
template = kwargs.get("template", "")
return self.domain.get_template(template).evoque(
title=title, content=content, **kwargs)
class SiteDirectory(Directory):
"""
This site displays the http request.
"""
def get_exports(self):
yield '', 'index', None, None
def index(self):
items = get_request().__dict__.items()
items.sort()
return page('HTTP Request', template="items.html", items=items)
def _q_traverse(self, components):
return self.index()
The templates
base.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>${title}</title>
</head>
<body class="standard">
$begin{content} ${content} $end{content}
$evoque{#content}
</body>
</html>
items.html
$overlay{base.html}
$begin{content}
<h1>${title}</h1>
<div style="margin:1em; padding:1em; border:1px solid gray;">
<dl>
$for{ key, value in items }
<dt>${key}</dt>
<dd style="white-space:pre">${pformat(value)}</dd>
$rof
</dl>
</div>
$end{content}