The Swiss Army Knife For Python Web Developers
Werkzeug started as a simple collection of various utilities for WSGI applications and has become one of the most advanced WSGI utility modules. It includes a powerful debugger, fully featured request and response objects, HTTP utilities to handle entity tags, cache control headers, HTTP dates, cookie handling, file uploads, a powerful URL routing system and a bunch of community contributed addon modules.
Werkzeug is unicode aware and doesn't enforce a specific template engine, database adapter or anything else. It doesn't even enforce a specific way of handling requests and leaves all that up to the developer.
Werkzeug is most useful for end user applications which should work in as many server environments as possible (such as blogs, wikis, bulletin boards, etc.).
Here is a tiny example that shows how you can use Werkzeug and the Mako template engine to generate simple dynamic pages.
#!/usr/bin/env python # -*- coding: utf-8 -*- from os import path from werkzeug import Request, Response, SharedDataMiddleware from werkzeug.routing import Map, Rule from werkzeug.exceptions import HTTPException from mako.lookup import TemplateLookup # calculate the path of the folder this file is in, the application will # look for templates in that path root_path = path.abspath(path.dirname(__file__)) # create a mako template loader for that folder and set the default input # encoding to utf-8 template_lookup = TemplateLookup(directories=[path.join(root_path, 'templates')], input_encoding='utf-8') # here we can create the URL map. Some sort of internal two-way # mod rewrite :-) The endpoints of those URLs are the names of the # templates without the .html suffix we will render in 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) ]) @Request.application def application(request): """A simple dispatch function that 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(request.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() # now create an empty response object with the correct mimetype. response = Response(mimetype='text/html') # now get the template and render it. Pass some useful stuff # into 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 = template_lookup.get_template(endpoint + '.html') response.data = template.render_unicode( request=request, response=response, endpoint=endpoint, url_for=lambda e, **v: adapter.build(e, v), url_values=values ) # now return the response return response except HTTPException, e: # if an http exception is catched we can return it as response # because those exceptions render standard error messages when # called as wsgi application return e # Apply a WSGI middleware for static file serving application = SharedDataMiddleware(application, { '/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)
And for completeness sake here is the “say_hello.html” template as one example:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <title>Hello World Fun!</title> <h1>Hello ${url_values['name']|h}!</h1> <p><a href="${url_for('index')}">back to the index</a></p>
Going to http://localhost:4000/hello/John gives you
“Hello John!” while http://localhost:4000/hello/ gives
you “Hello World!” because World was defined as URL default in our
URL map.
If you go to http://localhost:4000/ you will get an error
because the “index.html” template is missing. But you can easily add
that yourself.