Python Web Frameworks
Python Web Frameworks
Frameworks
Carlos de la Guardia
Carlos de la Guardia
Beijing
Boston Farnham
Sebastopol
Tokyo
First Edition
978-1-491-93810-2
[LSI]
Table of Contents
Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v
1. Python Web Framework Landscape. . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Web Framework List
31
35
40
45
48
53
59
61
61
63
64
65
66
5. Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
A. Python Web Development Fundamentals. . . . . . . . . . . . . . . . . . . . . . 69
iii
Introduction
vi
Introduction
Introduction
vii
CHAPTER 1
There are many options for building web applications with Python.
Pythons powerful yet flexible nature makes it perfect for this task.
Its a good idea to know whats available before going in that direc
tion, though. Perhaps one of the many existing options will suit your
needs and save you a ton of work.
To make it easier to know at a glance what frameworks are out there,
the following list shows 30 web frameworks that are active and have
more than 1,000 monthly downloads at the time of this writing. For
each framework, the list presents the following information:
Slogan
This is a short phrase that comes from the frameworks site or
documentation and attempts to convey the spirit of the frame
work according to its creators.
Description
In a nutshell, what this framework is and why you should use it.
Author
Main author, according to Python Package Index.
Website
Official website of the framework, or code repository if no site is
available.
Relative popularity
A very crude attempt at gauging a projects popularity, by nor
malizing the number of monthly downloads and generating a
score. Its purpose is only to give the reader a general idea about
how one framework compares to another in terms of number of
users. For example, Django, which is the Python framework
with the largest number of downloads, has 10 stars. At the other
end of the spectrum, BlueBream, which is barely above 1,000
downloads, has one star. This popularity scale should not be
taken too seriously.
Python versions
Shows the versions of Python that the framework runs on.
License
Shows the license under which the framework is distributed.
Documentation
This is a key part of any framework, because the more you know
about how to use it, the quicker you can get started and take
advantage of its features. Some people learn by example, so hav
ing tutorials and sample code can be very helpful too, both for
beginners and more advanced users. For each framework, docu
mentation is graded using a very simple scale: poor, adequate,
extensive, or comprehensive. Again, this is very subjective and
only meant as a simple guide to know what to expect.
Features
A short list of what the frameworks authors consider its best
features.
Other resources
This refers to resources other than web pages to get help and
information for a framework, like mailing lists and IRC chan
nels.
Persistence
Many web applications require a storage layer of some sort, usu
ally a database. Because of this, most web frameworks are
designed to use one or more specific data persistence options.
Templating
This is another very common feature of web frameworks. The
HTML markup for an application page is usually written in a
templating language.
Appier is an object-oriented Python web framework built for superfast app development. Its as lightweight as possible, but not too
lightweight. It gives you the power of bigger frameworks, without
the complexity.
Author
http://appier.hive.pt
Relative popularity
*****
Python versions
2.6 to 3.5
License
Apache
Documentation
Adequate
Other resources
None
Persistence
MongoDB
Templating
Jinja2
Features
REST dispatching
JSON response encoding
Web Framework List
Admin interface
i18n
Aspen
A Python web framework that makes the most of the filesystem.
Simplates are the main attraction.
Aspen maps your URLs directly to the filesystem. Its way simpler
than regular expression routing or object traversal.
Author
Gratipay, LLC
Website
http://aspen.io
Relative popularity
******
Python versions
2.6, 2.7
License
MIT
Documentation
Adequate
Other resources
IRC
Persistence
Any
Templating
BlueBream
The Zope Web Framework.
http://bluebream.zope.org
Relative popularity
*
Python versions
2.6, 2.7
License
ZPL
Documentation
Extensive
Other resources
Mailing list
Persistence
ZODB
Templating
ZPT
Features
Bobo
Web application framework for the impatient.
Jim Fulton
Website
http://bobo.digicool.com
Relative popularity
*
Python versions
2.6 to 3.5
License
ZPL
Documentation
Extensive
Other resources
Mailing list
Persistence
Any
Templating
Any
Features
Bottle
Fast and simple WSGI framework for small web applications.
Author
Marcel Hellkamp
Website
http://bottlepy.org
Relative popularity
******
Python versions
2.6 to 3.5
License
MIT
Documentation
Extensive
Other resources
Any
Templating
HTTP utilities
Single file distribution
CherryPy
A Minimalist Python Web Framework.
CherryPy Team
Website
http://www.cherrypy.org
Relative popularity
******
Web Framework List
Python versions
2.6 to 3.5
License
BSD
Documentation
Comprehensive
Other resources
Any
Templating
Any
Features
Clastic
A functional Python web framework that streamlines explicit
development practices while eliminating global state.
Clastic was created to fill the need for a minimalist web framework
that does exactly what you tell it to, while eliminating common pit
falls and delays in error discovery.
Author
Mahmoud Hashemi
Website
https://github.com/mahmoud/clastic
Relative popularity
*
Python versions
2.6, 2.7
License
BSD
8
Documentation
Basic
Other resources
None
Persistence
Any
Templating
Any
Features
No global state
Proactive URL route checking
Improved middleware paradigm
Cyclone
Facebooks Tornado on top of Twisted.
Alexandre Fiori
Website
https://cyclone.io
Relative popularity
***
Python versions
2.6, 2.7
License
Apache
Documentation
Adequate
Other resources
None
Persistence
Templating
Cyclone templates
Features
Asyncio stack
Command-line integration
Django
The web framework for perfectionists with deadlines.
https://djangoproject.com
Relative popularity
**********
Python versions
2.6 to 3.5
License
BSD
Documentation
Comprehensive
Other resources
Django ORM
Templating
10
Falcon
An unladen web framework for building APIs and app backends.
Kurt Griffiths
Website
http://falconframework.org
Relative popularity
****
Python versions
2.6 to 3.5
License
Apache
Documentation
Extensive
Other resources
Any
Templating
Any
Features
Fantastico
Pluggable, developer-friendly content publishing framework for
Python 3 developers.
11
Author
https://github.com/rcosnita/fantastico/
Relative popularity
*
Python versions
MIT
Documentation
Adequate
Other resources
None
Persistence
Fantastico ORM
Templating
Any
Features
Flask
Web development one drop at a time.
Armin Ronacher
Website
http://flask.pocoo.org
Relative popularity
*********
12
Python versions
BSD
Documentation
Comprehensive
Other resources
Any
Templating
Jinja2
Features
Built-in debugger
RESTful request dispatching
Allows modular applications with plugins
Extensible
Giotto
Web development simplified. An MVC framework supporting
Python 3.
Chris Priest
Website
http://giotto.readthedocs.org
Relative popularity
**
Python versions
Own
13
Documentation
Adequate
Other resources
Google group
Persistence
SQLAlchemy
Templating
Jinja2
Features
Grok
A smashing web framework.
Grok Team
Website
http://grok.zope.org
Relative popularity
***
Python versions
2.6, 2.7
License
ZPL
Documentation
Extensive
Other resources
Mailing list
14
Persistence
ZODB
Templating
kiss.py
MVC web framework in Python with Gevent, Jinja2, and Werkzeug.
Author
Stanislav Feldman
Website
http://stanislavfeldman.github.io/kiss.py
Relative popularity
*
Python versions
2.6, 2.7
License
Own
Documentation
Poor
Other resources
None
Persistence
Pewee
Templating
Jinja2
15
Features
Klein
Werkzeug + twisted.web.
Amber Brown
Website
http://klein.readthedocs.org
Relative popularity
*****
Python versions
2.6 to 3.5
License
MIT
Documentation
Adequate
Other resources
IRC
Persistence
Any
Templating
Twisted templates
Features
16
Morepath
A micro web framework with superpowers.
Martijn Faassen
Website
http://morepath.readthedocs.org/
Relative popularity
**
Python versions
2.6 to 3.5
License
BSD
Documentation
Extensive
Other resources
Any
Templating
Any
Features
17
Muffin
Web framework based on Asyncio stack.
Kirill Klenov
Website
https://github.com/klen/muffin
Relative popularity
*****
Python versions
2.6 to 3.5
License
MIT
Documentation
Poor
Other resources
None
Persistence
Any
Templating
Any
Features
Asyncio stack
Command-line integration
Pylons
A framework to make writing web applications in Python easy.
18
Author
http://www.pylonsproject.org/projects/pylons-framework/
Relative popularity
****
Python versions
2.6, 2.7
License
BSD
Documentation
Extensive
Other resources
SQLAlchemy
Templating
Pyramid
The start small, finish big, stay finished framework.
https://trypyramid.com
19
Relative popularity
******
Python versions
2.6 to 3.5
License
BSD derived
Documentation
Comprehensive
Other resources
Any
Templating
Any
Features
Tornado
A Python web framework and asynchronous networking library,
originally developed at FriendFeed.
Facebook
Website
http://www.tornadoweb.org
Relative popularity
*********
Python versions
2.6 to 3.5
20
License
Apache
Documentation
Adequate
Other resources
Any
Templating
Tornado templates
Features
TurboGears
The web framework that scales with you.
http://www.turbogears.org
Relative popularity
***
Python versions
2.6, 2.7
License
MIT
Documentation
Extensive
21
Other resources
SQLAlchemy
Templating
Genshi
Features
Twisted
Building the engine of your Internet.
Glyph Lefkowitz
Website
https://twistedmatrix.com
Relative popularity
*******
Python versions
2.6 to 3.5
License
MIT
Documentation
Adequate
Other resources
Any
22
Templating
twisted.web.template
Features
Uliweb
Unlimited Python web framework.
Limodou
Website
http://limodou.github.io/uliweb-doc/
Relative popularity
*
Python versions
2.6, 2.7
License
BSD
Documentation
Adequate
Other resources
Mailing list
Persistence
Uliorm
Templating
Uliweb
23
Features
Watson
Its elementary, my dear Watson.
A framework designed to get out of your way and let you code your
application rather than spend time wrangling with the framework. It
follows the convention over configuration ideal.
Author
Simon Coulton
Website
http://watson-framework.readthedocs.org
Relative popularity
*
Python versions
Own
Documentation
Adequate
Other resources
Mailing list
Persistence
Any
Templating
Jinja2
Features
Event-based
Dependency injection
Form library
24
web.py
Think about the ideal way to write a web app. Write the code to
make it happen.
Anand Chitipothu
Website
http://webpy.org
Relative popularity
*****
Python versions
2.6, 2.7
License
Public Domain
Documentation
Adequate
Other resources
Mailing list
Persistence
web.database
Templating
Templetor
Features
Simple to use
Own database and template libraries
Form library
25
web2py
Everything in one package with no dependencies.
Massimo Di Pierro
Website
http://web2py.com
Relative popularity
*
Python versions
2.6, 2.7
License
LGPL 3
Documentation
Extensive
Other resources
Mailing list
Persistence
DAL
Templating
web2py
Features
26
webapp2
Taking Google App Engines webapp to the next level!
Rodrigo Moraes
Website
http://webapp-improved.appspot.com/
Relative popularity
****
Python versions
2.6, 2.7
License
Apache
Documentation
Extensive
Other resources
Mailing list
Persistence
Google datastore
Templating
Jinja2, Mako
Features
WebPages
A Python web framework.
This project was designed for web developers who want to do more
in less time. To create a new project with Hello World and a database
connection, you only need a few minutes.
Web Framework List
27
Author
Anton Danilchenko
Website
https://github.com/webpages/webpages
Relative popularity
*
Python versions
MIT
Documentation
Poor
Other resources
Facebook
Persistence
WebPages ORM
Templating
WebPages templates
Features
wheezy.web
Pythons fastest web framework.
Andriy Kornatskyy
Website
http://wheezyweb.readthedocs.org
28
Relative popularity
***
Python versions
2.6 to 3.5
License
MIT
Documentation
Adequate
Other resources
None
Persistence
Any
Templating
High performance
Authentication/authorization
Model update/validation
29
CHAPTER 2
Some Frameworks to
Keep an Eye On
Django
Django is without a doubt the most popular web framework for
Python at the time of this writing. Django is a high-level framework,
designed to take care of most common web application needs.
Django makes a lot of decisions for you, from code layout to secu
rity. Its also very well documented, so its very easy to get a project
31
off the ground quickly. There are also many third-party applications
that can complement its many features nicely.
Django is very well-suited for database-driven web applications. Not
only does it include its own object-relational mapping (ORM), but it
can do automatic form generation based on the schemas and even
helps with migrations. Once your models are defined, a rich Python
API can be used to access your data.
Django also offers a dynamic administrative interface that lets
authenticated users add, change, and delete objects. This makes it
possible to get a nice-looking admin site up very early in the devel
opment cycle, and start populating the data and testing the models
while the user-facing parts of the application are taking shape.
In addition to all this, Django has a clean and simple way of map
ping URLs to code (views), and deals with things like caching, user
profiles, authentication, sessions, cookies, internationalization, and
more. Its templating language is simple, but its possible to create
custom tags for more advanced needs. Also, Django now supports
Jinja2, so theres that option if you require a bit more powerful tem
plating.
Quick Start
To install Django:
$ pip install Django
32
Representative Code
Djangos database integration is one of its strong suits, so lets take a
look at a few examples of that.
Defining models
from django.db import models
class Author(models.Model):
first_name = models.CharField(max_length=70)
last_name = models.CharField(max_length=70)
def __str__(self):
return self.full_name
@property
def full_name(self):
return '{} {}'.format(self.first_name, self.last_name)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=200)
description = models.TextField()
pub_date = models.DateField()
def __str__(self):
return self.title
Django
33
To make your models appear in the Django admin site, you need to
register them. This is done by inheriting from django.con
trib.admin.ModelAdmin, customizing the display and behavior of
the admin, and registering the class, like we do in the last line of the
previous example. Thats all the code needed to get a polished inter
face for adding, changing, and removing books from your site.
Djangos admin is very flexible, and has many customization hooks.
For example, the list_display attribute takes a list of fields and
displays their values in columns for each row of books, rather than
just showing the result of the __str__() method. The hooks are not
just for display purposes. You can add custom validators, or define
actions that operate on one or more selected instances and perform
domain specific transformations on the data.
Views
from django.shortcuts import render
from .models import Book
def publication_by_year(request, year):
books = Book.objects.filter(pub_date__year=year)
context = {'year': year, 'book_list': books}
return render(request, 'books/by_year.html', context)
34
This is a simple regular expression pattern that will match any fourdigit number after books/ in the URL. Lets say its a year. This
number is passed to the view, where we use the model API to filter
all existing books with this year in the publication date. Finally, the
render method is used to generate an HTML page with the result,
using a context object that contains any results that need to be
passed to the template.
Automated Testing
Django recommends using the unittest module for writing tests,
though any testing framework can be used. Django provides some
tools to help write tests, like TestCase subclasses that add Djangospecific assertions and testing mechanisms. It has a test client that
simulates requests and lets you examine the responses.
Djangos documentation has several sections dedicated to testing
applications, giving detailed descriptions of the tools it provides and
examples of how to test your applications.
Flask
Flask is a micro framework. Micro refers to the small core of the
framework, not the ability to create single-file applications. Flask
basically provides routing and templating, wrapped around a few
Flask
35
Quick Start
To install Flask:
$ pip install Flask
Representative Code
Lets look at a few examples of what Flask code looks like inside real
applications.
Flask
37
Sessions
from flask import Flask, session, redirect, url_for,
escape, request
app = Flask(__name__)
@app.route('/')
def index():
if 'username' in session:
return 'Logged in as %s' % escape(session['username'])
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return render_template('login.html')
@app.route('/logout')
def logout():
session.pop('username', None)
return redirect(url_for('index'))
app.secret_key = 'A secret'
Views
@app.route('/')
def show_entries():
cur = g.db.execute(
'select title, text from entries order by id desc')
38
Here we show how to define views. The route decorator that we saw
in the quickstart application is used to connect the add_entry
method with the /add URL. Note the use of the methods parameter
to restrict that view to POST requests.
We examine the session to see if the user is logged in, and if not,
abort the request. We assume that the request comes from a form
that includes the title and text parameters, which we extract from
the request to use in an insert statement. The request object refer
enced here has to be imported from flask, as in the sessions exam
ple.
Finally, a flash message is set up to display the change to the user,
and the browser is redirected to the main show_entries view. This
last view is simple, but it shows how to render a template, calling it
with the template name and the context data required for rendering.
Automated Testing
Flask exposes the Werkzeug test client to make testing applications
easier. It also provides test helpers to let tests access the request con
text as if they were views.
The documentation has a long section about testing applications.
The examples use unittest, but any other testing tool can be used.
Since Werkzeug is fully documented itself, there is very good infor
mation available about the test client too.
Flask
39
Tornado
Tornado is a combination of an asynchronous networking library
and a web framework. It is intended for use in applications that
require long-lived connections to their users.
Tornado has its own HTTP server based on its asynchronous
library. While its possible to use the web framework part of Tornado
with WSGI, to take advantage of its asynchronous nature its neces
sary to use it together with the web server.
In addition to typical web framework features, Tornado has libraries
and utilities to make writing asynchronous code easier. Instead of
depending on callbacks, Tornados coroutines library allows a pro
gramming style more similar to synchronous code.
Tornado includes a simple templating language. Unlike other tem
plating languages discussed here, in Tornado templates there are no
restrictions on the kind of expressions that you can use. Tornado
also has the concept of UI modules, which are special function calls
to render UI widgets that can include their own CSS and JavaScript.
Tornado also offers support for authentication and security, includ
ing secure cookies and CSRF protection. Tornado authentication
includes support for third-party login systems, like Google, Face
book, and Twitter.
Quick Start
To install Tornado:
$ pip install tornado
40
First, we define a request handler, which will simply write our Hello
World message in the response. A Tornado application usually con
sists of one or more handlers. The only prerequisite for defining a
handler is to subclass from the tornado.web.RequestHandler class.
To route requests to the appropriate handlers and take care of global
configuration options, Tornado uses an application object. In the
example above, we can see how the application is passed the routing
table, which in this case includes only one route. This route assigns
the root URL of the site to the MainHandler created above.
Once we have an application object, we configure it to listen to port
8888 and start the asynchronous loop to serve our application. Note
that theres no specific association of the application object we cre
ated and the ioloop, because the listen call actually creates an HTTP
server behind the scenes.
Representative Code
Since Tornados asynchronous nature is its main feature, lets see
some examples of that.
Tornado
41
In these three short examples, we can see how Tornado uses asyn
chronous calls and how that compares with the normal, synchro
nous calls that we would use in a WSGI application.
In the first example, we use tornado.HTTPClient to fetch a URL
from somewhere in the cloud. This is the regular case, and the syn
chronous_fetch call will not return until the client gets the response
back.
The second example uses the AsyncHTTPClient. The call will return
immediately after the fetch call, which is why Tornado can scale
more. The fetch method is passed a callback, which is a function
that will be executed when the client gets a response back. This
works, but it can lead to situations where you have to chain call
backs together, which can quickly become confusing.
For this reason, coroutines are the recommended way to write asyn
chronous code in Tornado. Coroutines take advantage of Python
generators to be able to return immediately with no callbacks. In the
fetch_coroutine method above, the gen.coroutine decorator
takes care of waiting without blocking for the client to finish fetch
ing the URL, and then passes the result to the yield.
Request handlers
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
return self.get_secure_cookie("user")
42
class MainHandler(BaseHandler):
def get(self):
if not self.current_user:
self.redirect("/login")
return
name = tornado.escape.xhtml_escape(self.current_user)
self.render("hello.html", title="Welcome", name)
class LoginHandler(BaseHandler):
def get(self):
self.render("login.html", title="Login Form")
def post(self):
self.set_secure_cookie("user",
self.get_argument("name"))
self.redirect("/")
application = tornado.web.Application([
(r"/", MainHandler),
(r"/login", LoginHandler)],
cookie_secret="__TODO:_GENERATE_A_RANDOM_VALUE_HERE__")
Since request handlers are classes, you can use inheritance to define
a base request handler that can have all the basic behavior needed
for your application. In BaseHandler in the previous example, the
get_current_user call will be available for both handlers defined in
the next example.
A handler should have a method for every HTTP method that it can
handle. In MainHandler, the GET method gets a look at the current
user and redirects to the login handler if it is not set (remember that
get_current_user is inherited from the base handler). If theres a
user, its name is escaped before being passed to the template. The
render method of a handler gets a template by name, optionally
passes it some arguments, and renders it.
LoginHandler has both GET and POST methods. The first renders the
login form, and the second sets a secure cookie with the name and
redirects to the MainHandler. The Tornado handlers have several
utility methods to help with requests. For example, the
self.get_argument method gets a parameter from the request. The
request itself can be accessed with self.request.
Tornado
43
UI modules
class Entry(tornado.web.UIModule):
def embedded_css(self):
return ".entry { margin-bottom: 1em; }"
def render(self, entry, show_comments=False):
return self.render_string(
"module-entry.html", entry=entry,
show_comments=show_comments)
UI modules are reusable UI widgets that you can use across your
application. They make it easy to design your page layouts using
independent components. UI modules subclass from tor
nado.web.UIModule and must include a render method. In the
example above, we define a UI module that represents a blog entry.
The render method can include arbitrary parameters, which usually
will be passed on to the module template, like in the example above.
A UI module can also include its own CSS and JavaScript. In our
example, we use the embedded_css method to return some CSS to
use for the entry class. There are also methods for embedding Java
Script and for pointing to CSS and JavaScript files.
Once the UI module is defined, we can call it within a template
with:
{ % module Entry(entry, show_comments=True) % }
Automated Testing
Tornado offers support classes for automated testing that allow
developers to test asynchronous code. It has a simple test runner,
which wraps unittest.main. It also has a couple of test helper func
tions.
Tornados test module is documented, but there is no specific tuto
rial or narrative section devoted to testing.
Bottle
Bottle is a true Python micro framework, in that its actually dis
tributed as a single file and has no dependencies outside of the
Python standard library. Its lightweight and fast.
Bottle focuses on providing clean and simple URL routing and tem
plating. It includes utilities for many web development needs, like
access to form data, cookies, headers, and file uploads. It also
includes its own HTTP server, so you dont need to set up anything
else to get your application running.
Even though its core is very small and its designed for small applica
tions, Bottle has a plugin architecture that allows it to be expanded
to fit more complex needs.
Quick Start
To install Bottle:
$ pip install bottle
The Bottle quick start is very simple. The route decorator connects
the index method to the /hello/<name> URL. Here, name is part of
a dynamic route. Its value is added to the hello message using a sim
ple string template.
Bottle
45
Representative Code
Even though Bottle is minimalistic, it does have a few nifty features,
as the following examples show.
Bottle uses a fast, simple template language that accepts both lines
and blocks of Python code. Indentation is ignored so that code can
be properly aligned, but in exchange for that its necessary to add an
end keyword after a normally indented block, like the for loop
above.
Using hooks
from bottle import hook, response, route
@hook('after_request')
def enable_cors():
response.headers['Access-Control-Allow-Origin'] = '*'
@route('/foo')
def say_foo():
return 'foo!'
46
@route('/bar')
def say_bar():
return {'type': 'friendly', 'content': 'Hi!'}
Wildcard filters
def list_filter(config):
''' Matches a comma separated list of numbers. '''
delimiter = config or ','
regexp = r'\d+(%s\d)*' % re.escape(delimiter)
def to_python(match):
return map(int, match.split(delimiter))
def to_url(numbers):
return delimiter.join(map(str, numbers))
return regexp, to_python, to_url
app = Bottle()
app.router.add_filter('list', list_filter)
@app.route('/follow/<ids:list>')
def follow_users(ids):
for id in ids:
follow(id)
47
Automated Testing
Bottle has no specific tools for testing applications. Its documenta
tion does not have a specific section devoted to testing, though it
does offer a couple of short recipes on how to do unit and functional
testing.
Pyramid
Pyramid is a general web application development framework. Its
designed for simplicity and speed. One of its main objectives is to
make it possible to start small without having to have a lot of knowl
edge about the framework, but allow an application to grow organi
cally as you learn more about Pyramid without sacrificing
performance and organization to do so.
Pyramid focuses on the most basic web application needs: mapping
URLs to code, supporting the best Python templating systems, serv
ing static assets, and providing security features. In addition to that,
it offers powerful and extensible configuration, extension, and addon systems. With Pyramid, its possible to override and customize
core code and add-ons from the outside, making it ideal for reusable
subsystems and even specialized frameworks.
48
Pyramid is the fruit of the merger between the Pylons and repoze.bfg
web frameworks. It is developed under the Pylons Project brand,
which sometimes causes some confusion with the old framework
name.
Quick Start
To install Pyramid:
$ pip install pyramid
Pyramid
49
Representative Code
Pyramid has a few unique features, like view predicates, renderers,
and asset specifications. Take a look at the following examples.
View predicates
from pyramid.view import view_config
@view_config(route_name='blog_action',
match_param='action=create', request_method='GET')
def show_create_page(request):
return Response('Creating...')
@view_config(route_name='blog_action',
match_param='action=create', request_method='POST')
def create_blog(request):
return Response('Created.')
@view_config(route_name='blog_action',
match_param='action=edit', request_method='GET')
def show_edit_page(request):
return Response('Editing...')
@view_config(route_name='blog_action',
match_param='action=edit', request_method='POST')
def edit_blog(request):
return Response('Edited.')
The first thing to note in the example above is the use of the
view_config decorator to configure views. In the Pyramid quick
start example we used config.add_view for the same purpose, but
using the decorator is a way to get the view declarations near the
actual code they call.
Next, look at the different parameters passed in to the view decora
tor. What sets Pyramids view configuration system apart is that
unlike most frameworks, Pyramid lets developers use several pieces
of information from the request to determine which views will be
called by the view lookup mechanism. This is done by adding predi
cates to the view configuration. Think of a predicate as a True or
False statement about the current request.
A view configuration declaration can have zero or more predicates,
and all things being equal, the view that has more predicates that all
50
Renderers
from pyramid.view import view_config
@view_config(renderer='json')
def hello_world(request):
return {'content':'Hello!'}
Pyramid
51
Asset specifications
from pyramid.view import view_config
@view_config(route_name='hello_world',
renderer='myapp:templates/hello.jinja2')
def hello(request):
return {'message': "Hello World!"}
52
Automated Testing
Pyramid has its own testing module for supporting tests. Like
other frameworks, it uses unittest in the documentation. Key Pyra
mid components, like the configurator, offer test helpers to simulate
some of their functionality.
Pyramids documentation includes a chapter about unit, integration,
and functional testing. The pyramid.testing module is also docu
mented, as are the various testing helpers. All official tutorials
include a testing section.
CherryPy
CherryPy is the oldest framework discussed here. It is perhaps the
original Python micro framework, as it focuses on matching a URL
to some view, and leaves everything else to the developer. It does
include its own web server, so it can serve static content as well. In
addition, CherryPy has built-in tools for caching, encoding, ses
sions, authorization, and more.
CherryPy has a fine-grained configuration system, which allows sev
eral configuration settings to be modified. Global configuration is
separate from application configuration, so its possible to run sev
eral applications in one process, each with its own configuration.
CherryPy is designed to be extensible, and offers several mecha
nisms for extensions and hook points. Since it has its own server,
these extension points include server-wide functions outside of the
regular request/response cycle. This gives CherryPy an added level
of extensibility.
CherryPy
53
Quick Start
To install CherryPy:
$ pip install cherrypy
Representative Code
Here are a couple of examples that showcase some of CherryPys
features.
REST API
import random
import string
54
import cherrypy
class StringGeneratorWebService(object):
exposed = True
def GET(self):
return cherrypy.session['mystring']
def POST(self, length=8):
some_string = ''.join(random.sample(string.hexdigits,
int(length)))
cherrypy.session['mystring'] = some_string
return some_string
if __name__ == '__main__':
conf = {
'/': {
'request.dispatch':
cherrypy.dispatch.MethodDispatcher(),
'tools.sessions.on': True,
}
}
cherrypy.quickstart(StringGeneratorWebService(), '/', conf)
CherryPy
55
@cherrypy.tools.json_out()
def encode_json(self):
return {'key': 'value'}
Tools
import time
import cherrypy
class TimingTool(cherrypy.Tool):
def __init__(self):
cherrypy.Tool.__init__(self, 'before_handler',
self.start_timer)
def _setup(self):
cherrypy.Tool._setup(self)
cherrypy.request.hooks.attach('before_finalize',
self.end_timer)
def start_timer(self):
cherrypy.request._time = time.time()
def end_timer(self):
duration = time.time() - cherrypy.request._time
cherrypy.log("Page handler took %.4f" % duration)
cherrypy.tools.timeit = TimingTool()
class Root(object):
@cherrypy.expose
@cherrypy.tools.timeit()
def index(self):
return "hello world"
Automated Testing
CherryPy provides a helper class for functional tests. It is a test case
class with some helpers. The documentation for this class is brief,
but includes an example.
CherryPy
57
CHAPTER 3
By this point, you know a little bit about which Python web frame
works are out there, and even have a little in-depth knowledge about
some of them. Still, you might be wondering which one is best for
you. This is not a question that can be answered here to your satis
faction, because every reader of this guide will have different needs.
However, I can offer some general guidelines and answer a couple of
frequently asked questions by people new to Python web develop
ment.
59
60
Desirable Features
While theres no general checklist for finding the best framework for
your use case, there are indeed a few things that you can look for
that could simplify your work a lot. It would be wise to at least con
sider these points while you decide which framework to use.
Documentation
This is probably the single most important thing to look for in a
framework. Good documentation lets you get up to speed quickly
and start worrying about your application right away rather than
trying to find out how to use the frameworks features.
Bonus points if the documentation is well-written, easy to follow,
and offers a variety of resources, like tutorials, cookbooks, and vid
eos. People learn in different ways, and some resources, like tutori
als, are usually much better for beginners. A discussion of advanced
topics can be very useful once you start familiarizing yourself with
the framework and trying more ambitious things.
Good documentation also evolves with the framework, so new relea
ses should always cover new features; there are few things as frus
trating as having to deal with outdated documentation when trying
to pinpoint if a problem is in your code or in the way you are trying
to use the framework.
61
Active Community
Its a good idea to try to connect with the community of users and
developers of your framework of choice. Theres no better way to
gauge existing interest in the framework and get a feel for how much
development work is under way to make it better. Usually, frame
works will have some mix of mailing lists, IRC channels, and web
forums. For most frameworks, these communication channels will
also be the official support mechanism, so it pays to find out about
them.
An active community is not only a good way of finding out if a
framework is alive and current, but it can also be a very nice com
plement to the documentation. Finding out how people have used a
feature in real life can be as helpful as the description of the feature
itself.
Reliability
The Python language evolves, new ways of working with the Web
come around frequently, and the open nature of the Web means
constant attention needs to be paid to security considerations. A
reliable framework is one that tries to stay current with all of these
events. Look for versions that mention compatibility with newer
Python releases, take advantage of new libraries and ways of doing
things, and offer occasional security fixes or notices.
Extensibility
Once you become proficient in the use of a framework, there usually
comes a time when you need to add some functionality or feature
that is not already part of it, and in a way that can be easily main
tained and understood. If a framework offers well-designed and
documented extension points, it will be easier to adapt to your spe
cial requirements in a way that doesnt break with version updates.
Also, it will be easier to take advantage of general extensions or plu
gins that other framework users have created.
62
CHAPTER 4
As the final step in our tour of Python web frameworks, well look
briefly at how to develop your very own framework. Even if you
dont plan to build one, knowing a bit about how the internals work
might be a good exercise.
63
Routing
You will need some way to match a URL to a view. The most com
mon way of doing this is using regular expression routes, like
Django or Flask. If you want to go for this approach, you should
consider using Werkzeug, which includes a routing system right out
of the box. There are also some routing libraries available on PyPI
that can be used with WebOb, or by themselves.
There are other ways to map URLs to views. Pyramid offers traver
sal, which treats your sites content as a tree and maps views to
resources or types of resources. CherryPy uses exposed methods
from regular Python classes. Maybe you can think about other
approaches. Just use something that feels natural to you.
Templates
There are a couple of very popular template systems for Python, and
its highly recommended to use one of them. Jinja2 and Mako are
two very good options.
Some frameworks are highly tailored to work with a chosen tem
plate system, while others leave that decision completely in the
hands of the developer. Whatever your choice, you cant go wrong,
as most of these template systems are proven and very stable.
Other Features
Most frameworks offer other features as part of the package.
Authentication is a common need and thus is usually provided for
in some way. There are many authentication systems and libraries
out there. The best advice here is to try to be flexible. You never
know how a user will need to authenticate their users.
Many frameworks make the assumption (perhaps less of a certainty
these days) that a relational database backend will be part of a web
application, and offer at least some degree of database support. If
64
Documentation
Even if your framework is only for internal use at your company, do
your best to document it. In fact, if you cant document it, it is better
to use one of the existing frameworks. Future maintainers of your
applications will thank you.
Good documentation consists of much more than class names and
methods. Some narrative documentation is very useful, and many
people find that code examples speak volumes. Beginners like tuto
rials and less technical explanations. Use a documentation tool, like
sphinx, to make documentation generation easier.
WebOb (http://webob.org)
WebOb provides objects that map much of the specified behavior of
HTTP, including header parsing, content negotiation, and correct
handling of conditional and range requests. Pyramid is one wellknown framework that uses WebOb.
Framework Building Blocks
65
Werkzeug (http://werkzeug.pocoo.org)
Werkzeug is 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, and a powerful URL
routing system. Flask, one of the most popular Python web frame
works, uses Werkzeug.
66
CHAPTER 5
Summary
67
APPENDIX A
the correct information for each user is used where required. The
browser provides some tools to keep track of that on the client side,
but the application needs to do some work, and the available mecha
nisms are often not enough for many applications.
Our application also has to have a way to get requests from a web
server, as well as sending back a response. That means more code
will be needed to communicate with the web server. The actual logic
in our application begins to feel rather small compared to the work
required to make it work on the Web.
Using pip
The recommended installer for Python is pip, and it is most fre
quently used to install packages from the Python Package Index. To
install a package:
71
Virtual Environments
A virtual environment for Python allows packages to be installed
in an isolated location, thus preventing version conflicts and unwan
ted upgrades. For example, an already working application could
require an earlier version of a popular library, but a new application
requires the newer version. With a single Python installation, you
risk affecting the application that is known to work fine when doing
the upgrade.
Virtual environments avoid this kind of conflict, allowing you to
have multiple virtual installations of the same Python version,
each with its own libraries and installation directories.
The most popular tool for creating virtual environments is virtua
lenv, which supports all active Python versions and includes pip and
setuptools by default on each virtual environment. Python 3.3 and
newer includes pyvenv, which performs a similar function.
Either of those tools makes it easy to create a virtual environment.
For virtualenv, virtualenv <directory> will set up a virtual environ
ment, including Python binaries, inside the chosen directory. For
pyvenv, pyvenv <directory> will do the same.
72