Werkzeug is a collection
of WSGI utility modules.
The werkzeug web site
presents (on welcome page click on nutshell to see the code)
a very simple demo application, that is described as:
A tiny WSGI application (about 50 lines of code) that
just uses werkzeug’s routing system and uses template names as
endpoints. These templates are then loaded with Mako,
rendered and returned as responses.
It is really trivial to make an equivalent application that uses
Evoque instead. The changes to the two concerned files
werkzeug_nutshell.py
and
say_hello.html
, shown further below,
are superficial:
- Initialize an Evoque
domain
, thus implicitly also defining
the default template collection. - Evoque’ing the template is identical, except for a different method name.
- In the sample
say_hello.html
template, remove the unnecessary
h
filter (Evoque automatically quotes all incoming unquoted data). - Make the sample
say_hello.html
template a valid HTML document 😉
werkzeug_nutshell.py
!/usr/bin/env python # -*- coding: utf-8 -*- from os import path from werkzeug import BaseRequest, BaseResponse, \ SharedDataMiddleware, responder from werkzeug.routing import Map, Rule from werkzeug.exceptions import HTTPException from evoque.domain import Domain # path for this file's folder # used as root for default template collection root_path = path.abspath(path.dirname(__file__)) # create an evoque template domain (and default collection) domain = Domain(root_path) # create the URL map. The endpoints are template names without the # .html extension, to be rendered by the `dispatch_request` function. url_map = Map([ Rule('/', endpoint='index'), Rule('/hello/', defaults={'name': 'World'}, endpoint='say_hello'), Rule('/hello/<name>', endpoint='say_hello'), Rule('/shared/<file>', endpoint='shared', build_only=True) ]) def dispatch_request(environ, start_response): """ A simple dispatch function that (if decorated with responder) is the complete WSGI application that does the template rendering and error handling. """ # first we bind the url map to the current request adapter = url_map.bind_to_environ(environ) # then we wrap all the calls in a try/except for HTTP exceptions try: # get the endpoint and the values (variable or parts) # of the adapter. If the match fails it raises a NotFound # exception which is a HTTPException which we catch endpoint, values = adapter.match() # create a new request object for the incoming WSGI environ request = BaseRequest(environ) # create an empty response object with the correct mimetype. response = BaseResponse(mimetype='text/html') # get the template and render it. Pass some useful stuff to # the template (request and response objects, the current # url endpoint, the url values and a url_for function which # can be used to generate urls template = domain.get_template(endpoint + '.html') response.write(template.evoque( request=request, response=response, endpoint=endpoint, url_for=lambda e, **v: adapter.build(e, v), url_values=values )) # return the response return response except HTTPException, e: # if an http exception is caught we can return it as # response because those exceptions render standard error # messages under wsgi return e # finish the wsgi application by wrapping it in a middleware that # serves static files in the shared folder and wrap the dispatch # function in a responder so that the return value is called as # wsgi application. application = SharedDataMiddleware(responder(dispatch_request), { '/shared': path.join(root_path, 'shared') }) # if the script is called from the command line start the # application with the development server on localhost:4000 if __name__ == '__main__': from werkzeug import run_simple run_simple('localhost', 4000, application)
say_hello.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html><head> <title>Hello World Fun!</title> </head><body> <h1>Hello ${url_values['name']}!</h1> <p><a href="${url_for('index')}">back to the index</a></p> </body></html>