web2py1 is a free, open-source web framework for agile development of secure database-driven web applications; it is written in Python2 and programmable in Python. web2py is a full-stack framework, meaning that it contains all the components you need to build fully functional web applications.
web2py is designed to guide a web developer to follow good software engineering practices, such as using the Model View Controller (MVC) pattern. web2py separates the data representation (the model) from the data presentation (the view) and also from the application logic and workflow (the controller). web2py provides libraries to help the developer design, implement, and test each of these three parts separately, and makes them work together.
web2py is built for security. This means that it automatically addresses many of the issues that can lead to security vulnerabilities, by following well established practices. For example, it validates all input (to prevent injections), escapes all output (to prevent cross-site scripting), renames uploaded files (to prevent directory traversal attacks). web2py leaves little choice to application developers in matters related to security.
web2py includes a Database Abstraction Layer (DAL) that writes SQL3 dynamically so that you, the developer, don't have to. The DAL knows how to generate SQL transparently for SQLite4, MySQL6, PostgreSQL5, MSSQL7, FireBird8, Oracle9, IBM DB210, Informix11, and Ingres12. The DAL can also generate function calls for Google BigTable when running on the Google App Engine (GAE)13. Once one or more database tables are defined, web2py also generates a fully functional web-based database administration interface to access the database and the tables.
web2py differs from other web frameworks in that it is the only framework to fully embrace the Web 2.0 paradigm, where the web is the computer. In fact, web2py does not require installation or configuration; it runs on any architecture that can run Python (Windows, Windows CE, Mac OS X, iOS, and Unix/Linux), and the development, deployment, and maintenance phases for the applications can be done via a local or remote web interface. web2py runs with CPython (the C implementation) and Jython (the Java implementation), on Python versions 2.4, 2.5 and 2.6, although "officially" it only supports 2.5 so that we can guarantee backward compatibility for applications.
web2py provides a ticketing system. If an error occurs, a ticket is issued to the user, and the error is logged for the administrator.
web2py is open source and released under the GPL2.0 license, but applications developed with web2py are not subject to any license constraint. In fact, as long as they do not contain web2py source code, they are not considered "derivative works". web2py also allows the developer to bytecode-compile applications and distribute them as closed source, although they will require web2py to run. The web2py license includes an exception that allows web developers to ship their products with original pre-compiled web2py binaries, without the accompanying source code.
Another feature of web2py is that we, its developers, commit to maintain backward compatibility in future versions. We have done so since the first release of web2py in October, 2007. New features have been added and bugs have been fixed, but if a program worked with web2py 1.0, that program will still work today.
Here are some examples of web2py statements that illustrate its power and simplicity. The following code:
1. | db.define_table('person', Field('name'), Field('image', 'upload')) |
creates a database table called "person" with two fields: "name", a string; and "image", something that needs to be uploaded (the actual image). If the table already exists but does not match this definition, it is altered appropriately.
Given the table defined above, the following code:
1. | form = crud.create(db.person) |
creates an insert form for this table that allows users to upload images. It also validates a submitted form, renames the uploaded image in a secure way, stores the image in a file, inserts the corresponding record in the database, prevents double submission, and eventually modifies the form itself by adding error messages if the data submitted by the user does not pass validation.
The following code:
1. | @auth.requires_permission('read','person') |
prevents visitors from accessing the function f unless the visitor is a member of a group whose members have permissions to "read" records of table "person". If the visitor is not logged in, he gets directed to a login page (provided by default by web2py).
The following code embeds a page component.
1. | {{=LOAD('other_controller','function.load',ajax=True, ajax_trap=True)}} |
This instructs web2py to load in a view the content generated by the other controller function (this works with any function). It loads the content via Ajax, embeds it into the current page (using the current layout, not the layout of the other_controller function), and traps all forms contained in the loaded content so that they are also submitted via Ajax without reloading the page. It can also LOAD content from non-web2py applications.
The LOAD helper allows very modular design of applications; it is discussed in some detail in the last chapter of this book.
Python programming typically follows these basic principles:
web2py fully embraces the first two principles by forcing the developer to use sound software engineering practices that discourage repetition of code. web2py guides the developer through almost all the tasks common in web application development (creating and processing forms, managing sessions, cookies, errors, etc.).
To some this may appear as magic, but it should not. Simply, in practice, some modules are already imported without you doing so. web2py is trying to avoid the annoying characteristic of other frameworks that force the developer to import the same modules at the top of every model and controller.
web2py, by importing its own modules, saves time and prevents mistakes, thus following the spirit of "don't repeat yourself" and "there should be only one way of doing things".
If the developer wishes to use other Python modules or third-party modules, those modules must be imported explicitly, as in any other Python program.
At its most fundamental level, a web application consists of a set of programs (or functions) that are executed when the corresponding URL is visited. The output of the program is returned to the visitor and rendered by the browser.
The purpose of web frameworks is to allow developers to build new app quickly, easily and without mistakes. This is done by providing APIs and tools that reduce and simplify the amount of coding that is required.
The two classic approaches for developing web applications are:
The first model is the one that was followed, for example, by early CGI scripts. The second model is followed, for example, by PHP16 (where the code is in PHP, a C-like language), ASP (where the code is in Visual Basic), and JSP (where the code is in Java).
Here is an example of a PHP program that, when executed, retrieves data from a database and returns an HTML page showing the selected records:
1. | <html><body><h1>Records</h1> |
The problem with this approach is that code is embedded into HTML, but the very same code also needs to generate additional HTML and to generate SQL statements to query the database, entangling multiple layers of the application and making it difficult to read and maintain. The situation is even worse for Ajax applications, and the complexity grows with the number of pages (files) that make up the application.
The functionality of the above example can be expressed in web2py with two lines of Python code:
1. | def index(): |
In this simple example, the HTML page structure is represented programmatically by the HTML, BODY, and H1 objects; the database db is queried by the select command; finally, everything
is serialized into HTML.
Notice that db is not a keyword but a user defined variable. We will use this name consistently to refer to a database connection to avoid confusion.
Web frameworks are typically categorized as one of two types: A "glued" framework is built by assembling (gluing together) several third-party components. A "full-stack" framework is built by creating components designed specifically to be tightly integrated and work together.
web2py is a full-stack framework. Almost all of its components are built from scratch and are designed to work
together, but they function just as well outside of the complete web2py framework. For example, the
Database Abstraction Layer (DAL) or the template language can be used independently of the
web2py framework by importing gluon.sql or gluon.template into your own Python applications. gluon is the name of the web2py module that contains system libraries. Some web2py libraries,
such as building and processing forms from database tables, have dependencies on other portions
of web2py. web2py can also work with third-party Python libraries, including other template languages
and DALs, but they will not be as tightly integrated as the original components.

The typical workflow of a request in web2py is described in the following diagram:

In the diagram:
Here is a minimal and complete MVC application, consisting of three files:
"db.py" is the model:
1. | db = DAL('sqlite://storage.sqlite') |
It connects to the database (in this example a SQLite database stored in the storage.sqlite file) and
defines a table called contacts. If the table does not exist, web2py creates it and, transparently
and in the background,
generates SQL code in the appropriate SQL dialect for the specific database engine used.
The developer can
see the generated SQL but does not need to change the code if the database back-end, which defaults to
SQLite, is replaced with MySQL, PostgreSQL, MSSQL, FireBird, Oracle, DB2, Informix, Interbase, Ingres,
or Google Big Tables in the Google App
Engine.
Once a table is defined and created, web2py also generates a fully functional web-based database administration interface, called appadmin, to access the database and the tables.
"default.py" is the controller:
1. | def contacts(): |
In web2py, URLs are mapped to Python modules and function calls. In this case, the controller contains
a single function (or "action") called contacts. An action may
return a string (the returned web page) or a Python dictionary (a set of
key:value pairs). If the function returns a dictionary, it is passed to a view with the same
name as the controller/function, which in turn renders the page. In this example, the function contacts performs
a database select and returns the resulting records as a value associated with the dictionary key records.
"default/contacts.html" is the view:
1. | {{extend 'layout.html'}} |
This view is called automatically by web2py after the associated controller function (action) is executed.
The purpose of this view is to render the variables in the returned dictionary records=... into HTML.
The view file is written in HTML, but it embeds Python code delimited by the special {{ and }}
delimiters. This is quite different from the PHP code example, because the only code
embedded into the HTML is "presentation layer" code. The "layout.html" file referenced at the top of the
view is provided by web2py and constitutes the basic layout for all web2py applications. The layout file can
easily be modified or replaced.
web2py is one of many web application frameworks, but it has compelling and unique features. web2py was originally developed as a teaching tool, with the following primary motivations:
WSGI (Web Server Gateway Interface) is an emerging Python standard for communication between a web server and Python applications).
Here is a screenshot of the main web2py admin interface:

OWASP has listed the top ten security issues that put web applications at risk. That list is reproduced here, along with a description of how each issue is addressed by web2py:
web2py was reviewed for security and you can find the result of the review in ref.20.
You can download web2py from the official web site:
web2py is composed of the following components:
web2py is distributed in source code, and in binary form for Microsoft Windows and for Mac OS X.
The source code distribution can be used in any platform where Python runs and includes the above-mentioned components. To run the source code, you need Python 2.5 pre-installed on the system. You also need one of the supported database engines installed. For testing and light-demand applications, you can use the SQLite database, included with Python 2.5.
The binary versions of web2py (for Windows and Mac OS X) include a Python 2.5 interpreter and the SQLite database. Technically, these two are not components of web2py. Including them in the binary distributions enables you to run web2py out of the box.
The following image depicts the overall web2py structure:

web2py is licensed under the GPL version 2 License. The full text of the license if available in ref.31.
The license includes but it is not limited to the following articles:
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
[...]
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License.
[...]
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
License Commercial Exception
The web2py license also includes a commercial exception:
You may distribute an application you developed with web2py together with an unmodified official binary distribution of web2py, as downloaded from the official website1, as long as you make it clear in the license of your application which files belong to the application and which files belong to web2py.
web2py was originally developed by and copyrighted by Massimo Di Pierro. The first version (1.0) was released in October, 2007. Since then it has been adopted by many users, some of whom have also contributed bug reports, testing, debugging, patches, and proofreading of this book.
Some of the major contributors are, in alphabetical order by first name:
Alexey Nezhdanov, Alvaro Justen, Attila Csipa, Bill Ferrett, Boris Manojlovic, Brian Meredyk, Bruno Rocha, Carsten Haese, Chris Clark, Chris Steel, Christian Foster Howes, Christopher Smiga, CJ Lazell, Craig Younkins, Daniel Lin, David Harrison Denes Lengyel, Douglas Soares de Andrade, Fran Boon, Francisco Gama, Fred Yanowski, Graham Dumpleton, Gyuris Szabolcs, Hamdy Abdel-Badeea, Hans Donner, Hans Murx, Hans C. v. Stockhausen, Ian Reinhart Geiser, Jonathan Benn, Jonathan Lundell, Josh Goldfoot, Jose Jachuf, Keith Yang, Kyle Smith, Limodou, Marcel Leuthi, Marcello Della Longa, Mariano Reingart, Mark Larsen, Mark Moore, Markus Gritsch, Martin Hufsky, Mateusz Banach, Michael Willis, Michele Comitini, Miguel Lopez, Nathan Freeze, Niall Sweeny, Niccolo Polo, Nicolas Bruxer, Ondrej Such, Pai, Phyo Arkar Lwin, Ramjee Ganti, Robin Bhattacharyya, Ruijun Luo (Iceberg), Scott Roberts, Sergey Podlesnyi, Sharriff Aina, Sriram, Durbha, Sterling Hankins, Stuart Rackham, Telman Yusupov, Thadeus Burgess, Tim Michelsen, Timothy Farrell, Vidul Nikolaev Petrov, Yair Eshel, Yarko Tymciurak, Younghyun Jo, Zahariash.
I am sure I forgot somebody, so I apologize.
I particularly thank Jonathan, Nathan, Thadeus, Tim, Iceberg, Denes, Hans and Fran for their major contributions to web2py and Alvaro, Bruno, Denes, Felipe, Graham, Jonathan, Hans, Kyle, Mark, Michele, Richard, Robin, Roman, Scott, Shane, Sharriff, Sriram, Sterling, Stuart, Thadeus and Yarko for proofreading various versions of this book. Their contribution was invaluable. If you find any errors in this book, they are exclusively my fault, probably introduced by a last-minute edit. I also thank Ryan Steffen of Wiley Custom Learning Solutions for help with publishing the first edition of this book.
web2py contains code from the following authors, whom I would like to thank:
Guido van Rossum for Python2, Peter Hunt, Richard Gordon, Timothy Farrell for the Rocket22 web server, Christopher Dolivet for EditArea23, Bob Ippolito for simplejson25, Simon Cusack and Grant Edwards for pyRTF26, Dalke Scientific Software for pyRSS2Gen27, Mark Pilgrim for feedparser28, Trent Mick for markdown229, Allan Saddi for fcgi.py, Evan Martin for the Python memcache module30, John Resig for jQuery32.
The logo used on the cover of this book was designed by Peter Kirchner at Young Designers.
I thank Helmut Epp (provost of DePaul University), David Miller (Dean of the College of Computing and Digital Media of DePaul University), and Estia Eichten (Member of MetaCryption LLC), for their continuous trust and support.
Finally, I wish to thank my wife, Claudia, and my son, Marco, for putting up with me during the many hours I have spent developing web2py, exchanging emails with users and collaborators, and writing this book. This book is dedicated to them.
This book includes the following chapters, besides this introduction:
This book only covers basic web2py functionalities and the API that ships with web2py. This book does not cover web2py appliances (i.e. ready made applications).
You can download web2py appliances from the corresponding web site 34.
You can find additional topics discussed on AlterEgo35, the interactive web2py FAQ.
This book has been written using the markmin syntax
PEP8 36 contains good style practices when programming with Python. You will find that web2py does not always follow these rules. This is not because of omissions or negligence; it is our belief that the users of web2py should follow these rules and we encourage it. We chose not to follow some of those rules when defining web2py helper objects in order to minimize the probability of name conflict with objects defined by the user.
For example, the class that represents a <div> is called DIV, while according to the
Python style reference it should have been called Div. We believe that, for this specific example that
using an all-upper-case "DIV" is a more natural choice. Moreover, this approach leaves programmers
free to create a class called "Div" if they choose to do so.
Our syntax also maps naturally into the DOM notation of most browsers (including, for example, Firefox).
According to the Python style guide, all-upper-case strings should be used for constants and not
variables. Continuing with our example, even considering that DIV is a class,
it is a special class that should never be modified by
the user because doing so would break other web2py applications.
Hence, we believe this qualifies the DIV class as
something that should be treated as a constant, further justifying our choice of notation.
In summary, the following conventions are followed:
DIV, A, FORM, URL).T is upper case despite the fact that it is an instance of a class and not a class itself. Logically the translator object performs an action similar to the HTML helpers, it affects rendering part of the presentation. Also, T needs to be easy to locate in the code and must have a short name.Table, Field, Query, Row, Rows, etc.In all other cases we believe we have followed, as much as possible, the Python Style Guide (PEP8). For example all instance objects are lower-case (request, response, session, cache), and all internal classes are capitalized.
In all the examples of this book, web2py keywords are shown in bold, while strings and comments are shown in italic.