# Web2py8.5plus3minus4plus24plus2minus2 Reference Manual, 5th Edition Web2py Manual

### web2py_manual_5th

User Manual:

Open the PDF directly: View PDF .
Page Count: 614

MASSIMO DI PIERRO

WEB2PY
COMPLETE REFERENCE MANUAL, 5TH EDITION

EXPERTS4SOLUTIONS

THE CONTENT OF THIS BOOK IS PROVIDED UNDER THE TERMS OF THE CREATIVE

THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY
USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND
AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU
THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF
SUCH TERMS AND CONDITIONS.
Limit of Liability/Disclaimer of Warranty: While the publisher and author have used their
best efforts in preparing this book, they make no representations or warranties with respect
to the accuracy or completeness of the contents of this book and specifically disclaim any
implied warranties of merchantability or fitness for a particular purpose. No warranty
may be created ore extended by sales representatives or written sales materials. The advice
and strategies contained herein may not be suitable for your situation. You should consult
with a professional where appropriate. Neither the publisher nor author shall be liable for
any loss of profit or any other commercial damages, including but not limited to special,
incidental, consequential, or other damages.

Massimo Di Pierro
School of Computing
DePaul University
243 S Wabash Ave
Chicago, IL 60604 (USA)
Email: massimo.dipierro@gmail.com

ISBN: 978-0-578-12021-8
Build Date: March 3, 2013

to my family

Contents
1 Introduction
1.1 Principles . . . . . . . .
1.2 Web frameworks . . .
1.3 Model-View-Controller
1.4 Why web2py . . . . . .
1.5 Security . . . . . . . . .
1.6 In the box . . . . . . .
1.8 Support . . . . . . . . .
1.9 Contribute . . . . . . .
1.10 Elements of style . . .
1.11 License . . . . . . . . .
1.12 Acknowledgments . .
2 The Python language
2.1 About Python . . .
2.2 Starting up . . . . .
2.3 help, dir . . . . . .
2.4 Types . . . . . . . .
2.4.1 str . . . . .
2.4.2 list . . . . .
2.4.3 tuple . . . .
2.4.4 dict . . . . .
2.6 for...in . . . . . . .

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

23
25
26
28
31
33
36
37
39
40
40
41
42

.
.
.
.
.
.
.
.
.
.

47
47
48
49
50
50
51
52
53
55
55

6

. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
try...except...else...finally . . . . . . .
def...return . . . . . . . . . . . . . . . . .
2.10.1 lambda . . . . . . . . . . . . . . . .
class . . . . . . . . . . . . . . . . . . . . .
Special attributes, methods and operators
File input/output . . . . . . . . . . . . . .
exec, eval . . . . . . . . . . . . . . . . . . .
import . . . . . . . . . . . . . . . . . . . . .
2.15.1 os . . . . . . . . . . . . . . . . . . .
2.15.2 sys . . . . . . . . . . . . . . . . . .
2.15.3 datetime . . . . . . . . . . . . . . .
2.15.4 time . . . . . . . . . . . . . . . . . .
2.15.5 cPickle . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

56
57
57
59
62
63
65
66
67
67
68
69
69
70
70

3 Overview
3.1 Startup . . . . . . . . . . . . . . . . . . . .
3.2 Simple examples . . . . . . . . . . . . . .
3.2.1 Say hello . . . . . . . . . . . . . . .
3.2.2 Debugging toolbar . . . . . . . . .
3.2.3 Let’s count . . . . . . . . . . . . . .
3.2.4 Say my name . . . . . . . . . . . .
3.2.5 Postbacks . . . . . . . . . . . . . .
3.2.6 Internationalization . . . . . . . .
3.3 An image blog . . . . . . . . . . . . . . . .
3.3.1 Adding authentication . . . . . . .
3.3.2 Adding grids . . . . . . . . . . . .
3.3.3 Configuring the layout . . . . . . .
3.4 A simple wiki . . . . . . . . . . . . . . . .
3.4.1 On date, datetime and time format
3.5 The built-in web2py wiki . . . . . . . . .
3.5.1 MARKMIN basics . . . . . . . . .
3.5.2 Oembed protocol . . . . . . . . . .
3.5.3 Referencing wiki content . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

73
73
77
77
82
82
83
85
88
89
103
105
107
108
119
120
122
123
124

2.7
2.8
2.9
2.10
2.11
2.12
2.13
2.14
2.15

while

if...elif...else

7

3.6

3.7

3.5.4 Wiki menus . . . . . . . . . . . . . .
3.5.5 Service functions . . . . . . . . . . .
3.5.6 Extending the auth.wiki feature . .
3.5.7 Components . . . . . . . . . . . . . .
More on admin . . . . . . . . . . . . . . . .
3.6.1 Site . . . . . . . . . . . . . . . . . . .
3.6.2 About . . . . . . . . . . . . . . . . .
3.6.3 Design . . . . . . . . . . . . . . . . .
3.6.4 Errors . . . . . . . . . . . . . . . . .
3.6.5 Mercurial . . . . . . . . . . . . . . .
3.6.6 Application Wizard (experimental)
3.6.7 Configuring admin . . . . . . . . . .
3.6.8 Mobile admin . . . . . . . . . . . . .
More on appadmin . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

4 The core
4.1 Command line options . . . . . . . . . . . . . . .
4.2 Workflow . . . . . . . . . . . . . . . . . . . . . . .
4.3 Dispatching . . . . . . . . . . . . . . . . . . . . .
4.4 Libraries . . . . . . . . . . . . . . . . . . . . . . .
4.5 Applications . . . . . . . . . . . . . . . . . . . . .
4.6 API . . . . . . . . . . . . . . . . . . . . . . . . . .
4.6.1 Accessing the API from Python modules
4.7 request . . . . . . . . . . . . . . . . . . . . . . . .
4.8 response . . . . . . . . . . . . . . . . . . . . . . . .
4.9 session . . . . . . . . . . . . . . . . . . . . . . . .
4.9.1 Separate sessions . . . . . . . . . . . . . .
4.10 cache . . . . . . . . . . . . . . . . . . . . . . . . .
4.11 URL . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.11.1 Absolute urls . . . . . . . . . . . . . . . .
4.11.2 Digitally signed urls . . . . . . . . . . . .
4.12 HTTP and redirect . . . . . . . . . . . . . . . . . .
4.13 Internationalization, and Pluralization with T . .
4.13.1 Determining the language . . . . . . . . .
4.13.2 Translating variables . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

125
125
126
127
128
128
131
131
135
138
139
140
142
142

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

145
145
149
152
155
160
162
163
165
170
174
177
177
180
182
182
184
185
186
188

8

4.14
4.15
4.16

4.17

4.18
4.19
4.20
4.21
4.22

4.13.3 Comments and multiple translations . . . .
4.13.4 Pluralization engine . . . . . . . . . . . . . .
4.13.5 Translations, pluralization, and MARKMIN
Cookies . . . . . . . . . . . . . . . . . . . . . . . . . .
Application init . . . . . . . . . . . . . . . . . . . . .
URL rewrite . . . . . . . . . . . . . . . . . . . . . . .
4.16.1 Parameter-based system . . . . . . . . . . . .
4.16.2 Pattern-based system . . . . . . . . . . . . .
4.16.3 Routes on error . . . . . . . . . . . . . . . . .
4.16.4 Static asset management . . . . . . . . . . . .
Running tasks in the background . . . . . . . . . . .
4.17.1 Cron . . . . . . . . . . . . . . . . . . . . . . .
4.17.2 Homemade task queues . . . . . . . . . . . .
4.17.3 Scheduler (experimental) . . . . . . . . . . .
Third party modules . . . . . . . . . . . . . . . . . .
Execution environment . . . . . . . . . . . . . . . . .
Cooperation . . . . . . . . . . . . . . . . . . . . . . .
Logging . . . . . . . . . . . . . . . . . . . . . . . . . .
WSGI . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.22.1 External middleware . . . . . . . . . . . . . .
4.22.2 Internal middleware . . . . . . . . . . . . . .
4.22.3 Calling WSGI applications . . . . . . . . . .

5 The views
5.1 Basic syntax . . . . . . . . . . . . . . .
5.1.1 for...in . . . . . . . . . . . . .
5.1.2 while . . . . . . . . . . . . . . .
5.1.3 if...elif...else . . . . . . . .
5.1.4 try...except...else...finally
5.1.5 def...return . . . . . . . . . . .
5.2 HTML helpers . . . . . . . . . . . . . .
5.2.1 XML . . . . . . . . . . . . . . . .
5.2.2 Built-in helpers . . . . . . . . .
5.2.3 Custom helpers . . . . . . . . .
5.3 BEAUTIFY . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

188
189
191
192
193
193
194
196
200
201
204
205
207
208
218
219
221
222
223
223
224
224

.
.
.
.
.
.
.
.
.
.
.

227
229
229
230
230
231
232
233
235
236
250
251

9

5.4

5.5

5.6
5.7

Server-side DOM and parsing . . . . .
5.4.1 elements . . . . . . . . . . . . .
5.4.2 components . . . . . . . . . . . .
5.4.3 parent and siblings . . . . . . .
5.4.4 Replacing elements . . . . . . .
5.4.5 flatten . . . . . . . . . . . . .
5.4.6 Parsing . . . . . . . . . . . . . .
Page layout . . . . . . . . . . . . . . . .
5.5.1 Default page layout . . . . . .
5.5.2 Customizing the default layout
5.5.3 Mobile development . . . . . .
Functions in views . . . . . . . . . . .
Blocks in views . . . . . . . . . . . . .

6 The database abstraction layer
6.1 Dependencies . . . . . . . . . . . .
6.2 Connection strings . . . . . . . . .
6.2.1 Connection pooling . . . .
6.2.2 Connection failures . . . . .
6.2.3 Replicated databases . . . .
6.3 Reserved keywords . . . . . . . . .
6.4 DAL, Table, Field . . . . . . . . . . .
6.5 Record representation . . . . . . .
6.6 Migrations . . . . . . . . . . . . . .
6.7 Fixing broken migrations . . . . .
6.8 insert . . . . . . . . . . . . . . . . .
6.9 commit and rollback . . . . . . . . .
6.10 Raw SQL . . . . . . . . . . . . . . .
6.10.1 Timing queries . . . . . . .
6.10.2 executesql . . . . . . . . . .
6.10.3 _lastsql . . . . . . . . . . .
6.11 drop . . . . . . . . . . . . . . . . . .
6.12 Indexes . . . . . . . . . . . . . . . .
6.13 Legacy databases and keyed tables
6.14 Distributed transaction . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

252
252
254
254
254
255
255
255
259
262
263
264
265

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

267
267
269
271
272
272
272
273
275
281
282
283
284
285
285
285
286
287
287
287
288

10

6.15 More on uploads . . . . . . . . . . . . . . . . . . . . .
6.16 Query, Set, Rows . . . . . . . . . . . . . . . . . . . . . . .
6.17 select . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.17.1 Shortcuts . . . . . . . . . . . . . . . . . . . . . .
6.17.2 Fetching a Row . . . . . . . . . . . . . . . . . . .
6.17.3 Recursive selects . . . . . . . . . . . . . . . . .
6.17.4 Serializing Rows in views . . . . . . . . . . . . .
6.17.5 orderby, groupby, limitby, distinct, having . . .
6.17.6 Logical operators . . . . . . . . . . . . . . . . .
6.17.7 count, isempty, delete, update . . . . . . . . . .
6.17.8 Expressions . . . . . . . . . . . . . . . . . . . .
6.17.9 case . . . . . . . . . . . . . . . . . . . . . . . .
6.17.10 update_record . . . . . . . . . . . . . . . . . . .
6.17.11 Inserting and updating from a dictionary . . .
6.17.12 first and last . . . . . . . . . . . . . . . . . . .
6.17.13 as_dict and as_list . . . . . . . . . . . . . . . .
6.17.14 Combining rows . . . . . . . . . . . . . . . . .
6.17.15 find, exclude, sort . . . . . . . . . . . . . . . . .
6.18 Other methods . . . . . . . . . . . . . . . . . . . . . .
6.18.1 update_or_insert . . . . . . . . . . . . . . . . .
6.18.2 validate_and_insert, validate_and_update . . .
6.18.3 smart_query (experimental) . . . . . . . . . . .
6.19 Computed fields . . . . . . . . . . . . . . . . . . . . .
6.20 Virtual fields . . . . . . . . . . . . . . . . . . . . . . . .
6.20.1 New style virtual fields . . . . . . . . . . . . .
6.20.2 Old style virtual fields . . . . . . . . . . . . . .
6.21 One to many relation . . . . . . . . . . . . . . . . . . .
6.21.1 Inner joins . . . . . . . . . . . . . . . . . . . . .
6.21.2 Left outer join . . . . . . . . . . . . . . . . . . .
6.21.3 Grouping and counting . . . . . . . . . . . . .
6.22 Many to many . . . . . . . . . . . . . . . . . . . . . . .
6.23 list:, and contains . . . . . . . . . . . . . . . .
6.24 Other operators . . . . . . . . . . . . . . . . . . . . . .
6.24.1 like, regexp, startswith, contains, upper, lower
6.24.2 year, month, day, hour, minutes, seconds . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

289
290
291
293
293
294
295
297
299
299
300
300
301
301
302
302
302
303
304
304
305
305
306
307
307
308
310
311
313
313
314
315
317
317
318

11

6.25
6.26

6.27
6.28
6.29

6.24.3 belongs . . . . . . . . . . . . . . . . . . . . . . . .
6.24.4 sum, avg, min, max and len . . . . . . . . . . . . . .
6.24.5 Substrings . . . . . . . . . . . . . . . . . . . . . .
6.24.6 Default values with coalesce and coalesce_zero
Generating raw sql . . . . . . . . . . . . . . . . . . . . .
Exporting and importing data . . . . . . . . . . . . . . .
6.26.1 CSV (one Table at a time) . . . . . . . . . . . . .
6.26.2 CSV (all tables at once) . . . . . . . . . . . . . .
6.26.3 CSV and remote database synchronization . . .
6.26.4 HTML and XML (one Table at a time) . . . . . .
6.26.5 Data representation . . . . . . . . . . . . . . . .
Caching selects . . . . . . . . . . . . . . . . . . . . . . .
Self-Reference and aliases . . . . . . . . . . . . . . . . .
Advanced features . . . . . . . . . . . . . . . . . . . . .
6.29.1 Table inheritance . . . . . . . . . . . . . . . . . .
6.29.2 filter_in and filter_out . . . . . . . . . . . . .
6.29.3 before and after callbacks . . . . . . . . . . . . .
6.29.4 Record versioning . . . . . . . . . . . . . . . . .
6.29.5 Common fields and multi-tenancy . . . . . . . .
6.29.6 Common filters . . . . . . . . . . . . . . . . . . .
6.29.7 Custom Field types (experimental) . . . . . . .
6.29.8 Using DAL without define tables . . . . . . . .
6.29.9 PostGIS, SpatiaLite, and MS Geo (experimental)
6.29.10 Copy data from one db into another . . . . . . .
6.29.11 Note on new DAL and adapters . . . . . . . . .
6.29.12 Gotchas . . . . . . . . . . . . . . . . . . . . . . .

7 Forms and validators
7.1 FORM . . . . . . . . . . . . . . . . . . . . . .
7.1.1 The process and validate methods
7.1.2 Hidden fields . . . . . . . . . . . .
7.1.3 keepvalues . . . . . . . . . . . . . .
7.1.4 onvalidation . . . . . . . . . . . . .
7.1.5 Detect record change . . . . . . . .
7.1.6 Forms and redirection . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

319
319
320
320
321
322
322
322
323
325
326
327
328
329
329
330
330
332
333
334
334
335
336
337
338
341

.
.
.
.
.
.
.

345
346
349
350
352
352
353
353

12

Multiple forms per page . . . . . . . . .
Sharing forms . . . . . . . . . . . . . . .
Adding buttons to FORMs . . . . . . .
More about manipulation of FORMs .
SQLFORM . . . . . . . . . . . . . . . . . . . . . . .
7.2.1 SQLFORM and insert/update/delete . . .
7.2.2 SQLFORM in HTML . . . . . . . . . . . . .
7.2.3 SQLFORM and uploads . . . . . . . . . . .
7.2.4 Storing the original filename . . . . . .
7.2.5 autodelete . . . . . . . . . . . . . . . . .
7.2.6 Links to referencing records . . . . . . .
7.2.7 Pre-populating the form . . . . . . . . .
7.2.8 Adding extra form elements to SQLFORM
7.2.9 SQLFORM without database IO . . . . . .
Other types of Forms . . . . . . . . . . . . . . .
7.3.1 SQLFORM.factory . . . . . . . . . . . . . .
7.3.2 One form for multiple tables . . . . . .
7.3.3 Confirmation Forms . . . . . . . . . . .
7.3.4 Form to edit a dictionary . . . . . . . .
CRUD . . . . . . . . . . . . . . . . . . . . . . . .
7.4.1 Settings . . . . . . . . . . . . . . . . . .
7.4.2 Messages . . . . . . . . . . . . . . . . . .
7.4.3 Methods . . . . . . . . . . . . . . . . . .
7.4.4 Record versioning . . . . . . . . . . . .
Custom forms . . . . . . . . . . . . . . . . . . .
7.5.1 CSS conventions . . . . . . . . . . . . .
7.5.2 Hide errors . . . . . . . . . . . . . . . .
Validators . . . . . . . . . . . . . . . . . . . . .
7.6.1 Validators . . . . . . . . . . . . . . . . .
7.6.2 Database validators . . . . . . . . . . .
7.6.3 Custom validators . . . . . . . . . . . .
7.6.4 Validators with dependencies . . . . . .
Widgets . . . . . . . . . . . . . . . . . . . . . . .
7.7.1 Autocomplete widget . . . . . . . . . .
SQLFORM.grid and SQLFORM.smartgrid . . . . . . .
7.1.7
7.1.8
7.1.9
7.1.10

7.2

7.3

7.4

7.5

7.6

7.7
7.8

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

354
355
356
356
356
361
363
364
366
367
367
369
370
370
371
371
372
373
373
374
375
377
378
380
382
383
384
385
386
397
399
401
401
403
404

13

8 Emails and SMS
8.1 Setting up email . . . . . . . . . . . . . . . . . . . . .
8.1.1 Configuring email for Google App Engine .
8.1.2 x509 and PGP Encryption . . . . . . . . . . .
8.2 Sending emails . . . . . . . . . . . . . . . . . . . . .
8.2.1 Simple text email . . . . . . . . . . . . . . . .
8.2.2 HTML emails . . . . . . . . . . . . . . . . . .
8.2.3 Combining text and HTML emails . . . . . .
8.2.4 cc and bcc emails . . . . . . . . . . . . . . . .
8.2.5 Attachments . . . . . . . . . . . . . . . . . . .
8.2.6 Multiple attachments . . . . . . . . . . . . . .
8.3 Sending SMS messages . . . . . . . . . . . . . . . . .
8.4 Using the template system to generate messages . .
8.5 Sending messages using a background task . . . . .
8.6 Reading and managing email boxes (Experimental)
8.6.1 Connection . . . . . . . . . . . . . . . . . . .
8.6.2 Fetching mail and updating flags . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

413
413
414
414
415
415
415
416
416
416
416
416
417
418
419
420
421

9 Access Control
9.1 Authentication . . . . . . . . . . . . . . . . . . . .
9.1.1 Restrictions on registration . . . . . . . .
9.1.2 Integration with OpenID, Facebook, etc.
9.1.4 Customizing Auth . . . . . . . . . . . . . .
9.1.5 Renaming Auth tables . . . . . . . . . . .
9.1.7 Record versioning . . . . . . . . . . . . .
9.1.8 Mail and Auth . . . . . . . . . . . . . . . .
9.2 Authorization . . . . . . . . . . . . . . . . . . . .
9.2.1 Decorators . . . . . . . . . . . . . . . . . .
9.2.2 Combining requirements . . . . . . . . .
9.2.3 Authorization and CRUD . . . . . . . . .
9.2.5 Access Control and Basic Authentication
9.2.6 Manual Authentication . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

425
428
431
432
434
435
437
438
444
445
446
448
449
450
451
451
452

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

14

9.3

9.2.7 Settings and messages . . . . . . . . . . . . . . . . . . 452
Central Authentication Service . . . . . . . . . . . . . . . . . 458
9.3.1 Using web2py to authorize non-web2py apps . . . . 460

10 Services
10.1 Rendering a dictionary . . . . . . . .
10.1.1 HTML, XML, and JSON . . .
10.1.2 Generic views . . . . . . . . .
10.1.3 Rendering Rows . . . . . . . .
10.1.4 Custom formats . . . . . . . .
10.1.5 RSS . . . . . . . . . . . . . . .
10.1.6 CSV . . . . . . . . . . . . . . .
10.2 Remote procedure calls . . . . . . .
10.2.1 XMLRPC . . . . . . . . . . . .
10.2.2 JSONRPC . . . . . . . . . . .
10.2.3 JSONRPC and Pyjamas . . .
10.2.4 AMFRPC . . . . . . . . . . .
10.2.5 SOAP . . . . . . . . . . . . . .
10.3 Low level API and other recipes . .
10.3.1 simplejson . . . . . . . . . . .
10.3.2 PyRTF . . . . . . . . . . . . .
10.3.3 ReportLab and PDF . . . . .
10.4 Restful Web Services . . . . . . . . .
10.4.1 parse_as_rest (experimental)
10.4.2 smart_query (experimental) .
10.4.3 Access Control . . . . . . . .
10.5 Services and Authentication . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

463
463
464
464
466
467
467
469
470
472
473
474
477
480
480
480
481
482
483
486
491
491
492

11 jQuery and Ajax
11.1 web2py_ajax.html . . . . . . . . . .
11.2 jQuery effects . . . . . . . . . . . .
11.2.1 Conditional fields in forms
11.2.2 Confirmation on delete . .
11.3 The ajax function . . . . . . . . . .
11.3.1 Eval target . . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

495
495
500
504
506
507
508

.
.
.
.
.
.

15

11.3.2 Auto-completion . . . . . . . . . . . . . . . . . . . . . 508
11.3.3 Ajax form submission . . . . . . . . . . . . . . . . . . 511
11.3.4 Voting and rating . . . . . . . . . . . . . . . . . . . . . 512
12 Components and plugins
12.1 Components . . . . . . . . . . . . . . . . . . . . . .
12.1.1 Client-Server component communications
12.1.2 Trapped Ajax links . . . . . . . . . . . . . .
12.2 Plugins . . . . . . . . . . . . . . . . . . . . . . . . .
12.2.1 Component plugins . . . . . . . . . . . . .
12.2.2 Plugin manager . . . . . . . . . . . . . . . .
12.2.3 Layout plugins . . . . . . . . . . . . . . . .
12.2.4 Plugins repositories . . . . . . . . . . . . .

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

515
515
520
521
522
526
527
528
529

13 Deployment recipes
13.1 anyserver.py . . . . . . . . . . . . . . . . . . . . . . . . .
13.2 Linux and Unix . . . . . . . . . . . . . . . . . . . . . . .
13.2.1 One step production deployment . . . . . . . .
13.2.2 Apache setup . . . . . . . . . . . . . . . . . . . .
13.2.3 mod_wsgi . . . . . . . . . . . . . . . . . . . . . .
13.2.4 Setting password . . . . . . . . . . . . . . . . . .
13.2.5 mod_wsgi and SSL . . . . . . . . . . . . . . . . .
13.2.6 mod_proxy . . . . . . . . . . . . . . . . . . . . .
13.2.7 Start as Linux daemon . . . . . . . . . . . . . . .
13.2.8 Nginx . . . . . . . . . . . . . . . . . . . . . . . .
13.2.9 Lighttpd . . . . . . . . . . . . . . . . . . . . . . .
13.2.10 Shared hosting with mod_python . . . . . . . .
13.2.11 Cherokee with FastCGI . . . . . . . . . . . . . .
13.2.12 Postgresql . . . . . . . . . . . . . . . . . . . . . .
13.2.13 Start the scheduler as a Linux service (upstart)
13.3 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . .
13.3.1 Apache and mod_wsgi . . . . . . . . . . . . . .
13.3.2 Start as Windows service . . . . . . . . . . . . .
13.3.3 Start the scheduler as a Windows service . . . .
13.4 Securing sessions and admin . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

531
534
535
535
535
536
539
539
540
542
543
546
548
548
550
551
552
552
555
556
556

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

16

13.5 Efficiency and scalability . . . . . . . . . . . . . . .
13.5.1 Efficiency tricks . . . . . . . . . . . . . . . .
13.5.2 Sessions in database . . . . . . . . . . . . .
13.5.3 HAProxy a high availability load balancer
13.5.4 Cleaning up sessions . . . . . . . . . . . . .
13.5.5 Uploading files in database . . . . . . . . .
13.5.6 Collecting tickets . . . . . . . . . . . . . . .
13.5.7 Memcache . . . . . . . . . . . . . . . . . . .
13.5.8 Sessions in memcache . . . . . . . . . . . .
13.5.9 Caching with Redis . . . . . . . . . . . . .
13.5.10 Sessions in Redis . . . . . . . . . . . . . . .
13.5.11 Removing applications . . . . . . . . . . . .
13.5.12 Using replicated databases . . . . . . . . .
13.5.13 Compress static files . . . . . . . . . . . . .
13.6 Deploying on PythonAnywhere . . . . . . . . . .
13.7 Deploying on Heroku . . . . . . . . . . . . . . . .
13.8 Deploying on EC2 . . . . . . . . . . . . . . . . . . .
13.9 Deploying on Google App Engine . . . . . . . . .
13.9.1 Configuration . . . . . . . . . . . . . . . . .
13.9.2 Running and deployment . . . . . . . . . .
13.9.3 Configuring the handler . . . . . . . . . . .
13.9.4 Avoid the filesystem . . . . . . . . . . . . .
13.9.5 Memcache . . . . . . . . . . . . . . . . . . .
13.9.6 Datastore issues . . . . . . . . . . . . . . . .
13.9.7 GAE and https . . . . . . . . . . . . . . . .
14 Other recipes
14.1 Upgrading . . . . . . . . . . . . . . . . . . . . . .
14.2 How to distribute your applications as binaries
14.3 WingIDE, Rad2Py, and Eclipse . . . . . . . . . .
14.4 SQLDesigner . . . . . . . . . . . . . . . . . . . . .
14.5 Publishing a folder . . . . . . . . . . . . . . . . .
14.6 Functional testing . . . . . . . . . . . . . . . . . .
14.7 Building a minimalist web2py . . . . . . . . . . .
14.8 Fetching an external URL . . . . . . . . . . . . .

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

557
559
559
560
561
562
563
564
565
565
565
566
566
567
568
570
572
573
574
575
577
577
578
578
579

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

581
581
581
582
583
584
585
587
588

17

14.9 Pretty dates . . . . . . . . . . . . . . . .
14.10Geocoding . . . . . . . . . . . . . . . . .
14.11Pagination . . . . . . . . . . . . . . . . .
14.12httpserver.log and the Log File Format
14.13Populating database with dummy data
14.14Accepting credit card payments . . . . .
14.14.1 Google Wallet . . . . . . . . . . .
14.14.2 Paypal . . . . . . . . . . . . . . .
14.14.3 Stripe.com . . . . . . . . . . . . .
14.14.4 Authorize.Net . . . . . . . . . . .
14.15Dropbox API . . . . . . . . . . . . . . . .
14.16Twitter API . . . . . . . . . . . . . . . . .
14.17Streaming virtual files . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

588
589
589
590
591
592
593
594
594
596
597
598
599

Index

603

Bibliography

609

CONTENTS

19

Preface
I believe that the ability to easily build high quality web applications is of
critical importance for the growth of a free and open society. This prevents
the biggest players from monopolizing the flow of information.
Hence I started the web2py project in 2007, primarily as a teaching tool with
the goal of making web development easier, faster, and more secure. Over
time, it has managed to win the affection of thousands of knowledgeable
users and hundreds of developers. Our collective effort has created one
of the most full-featured Open Source Web Frameworks for enterprise web
development.
As a result, in 2011, web2py won the Bossie Award for best Open Source
Development Software, and in 2012 it won the Technology of the Year award
from InfoWorld.
As you will learn in the following pages, web2py tries to lower the barrier of
entry to web development by focusing on three main goals:
Ease of use. This means reducing the learning and deployment time as well
as development and maintenance costs. This is why web2py is a full-stack
framework without dependencies. It requires no installation and has no
configuration files. Everything works out of the box, including a web server,
database and a web-based IDE that gives access to all the main features. The
API includes just 12 core objects, which are easy to work with and memorize.
It can interoperate with most web servers, databases and all Python libraries.
Rapid development. Every function of

web2py

has a default behavior (which

22

web2py complete reference manual, 5th edition

can be overridden). For example, as soon as you have specified your data
Also, web2py automatically generates forms for your data and it allows you to
easily expose the data in HTML, XML, JSON, RSS, etc. web2py provides some
high level widgets such as the wiki and the grid to rapidly build complex
applications.
Security.
The web2py Database Abstraction Layer (DAL) eliminates
SQL Injections. The template language prevents Cross Site Scripting
vulnerabilities. The forms generated by web2py provide field validation and
block Cross Site Request Forgeries. Passwords are always stored hashed.
Sessions are stored server-side by default to prevent Cookie Tampering.
Session cookies are UUID to prevent Session Hijacking.
is built from the user perspective and is constantly being optimized
internally to become faster and leaner, whilst always maintaining backwards
compatibility.
web2py

web2py is free for you to use. If you benefit from it, I hope you will feel
encouraged to pay it forward by contributing back to society in whatever form
you choose.

1
Introduction
web2py [1] is a free, open-source web framework for agile development
of secure database-driven web applications; it is written in Python [2]
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 takes care of main security issues, so developers have
less chances of introducing vulnerabilities. web2py includes a Database
Abstraction Layer (DAL) that writes SQL [3] dynamically so that you, the
developer, don’t have to. The DAL knows how to generate SQL transparently
for SQLite [4], MySQL [5], PostgreSQL [6], MSSQL [7], FireBird [8], Oracle [9],
IBM DB2 [10], Informix [11], Ingres [12], and MongoDB [13]. The DAL can
also generate function calls for the Google Datastore when running on the

24

web2py complete reference manual, 5th edition

Google App Engine (GAE) [14]. Experimentally we support more databases
and new ones are constantly added. Please check on the web2py web site
and mailing list for more recent adapters. Once one or more database
tables are defined, web2py automatically generates a fully functional webbased 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 PyPy
(Python written in Python), on Python versions 2.5, 2.6, and 2.7. web2py
provides a ticketing system for error events. 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 LGPL version 3 license.
Another important 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 work even better today.
Here are some examples of web2py statements that illustrate its power and
simplicity. The following code:
1

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 = SQLFORM(db.person).process()

creates an insert form for this table that allows users to upload images.
It also validates the 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

introduction

25

itself by adding error messages if the data submitted by the user does not
pass validation.
This code embeds a fully working wiki with tags, search, tag cloud,
permissions, media attachments, and oembed support:
1

def index(): return auth.wiki()

1
2

def f(): ....

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, the visitor gets directed to a login
page (provided by default by web2py). web2py also supports components,
i.e. actions which can be loaded in a view and interact with the visitor via
allows very modular design of applications; it is discussed in chapter 3 in the
context of the wiki and, in some detail, in the last chapter of this book.
This 5th edition of the book describes web2py 2.4.1 and later versions.

1.1

Principles

Python programming typically follows these basic principles:
• Don’t repeat yourself (DRY).
• There should be only one way of doing things.
• Explicit is better than implicit.
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,
web2py differs from other frameworks with regard to the third principle,
which sometimes conflicts with the other two. In particular, web2py does

26

web2py complete reference manual, 5th edition

not import user applications, but executes them in a predefined context. This
context exposes the Python keywords, as well as the web2py keywords.
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.

1.2

Web frameworks

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 apps
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:
• Generating HTML [15] [16] programmatically.
• Embedding code into HTML pages.
The first model is the one that was followed, for example, by early CGI
scripts. The second model is followed, for example, by PHP [17] (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
2

# Records

$name Phone:$phone

# {{=message}}

## Number of visits: {{=counter}}

When you visit the index page again (and again) you should get the following HTML page: The counter is associated with each visitor, and is incremented each time the visitor reloads the page. Different visitors see different counters. 3.2.4 Say my name Now create two pages (first and second), where the first page creates a form, asks the visitor’s name, and redirects to the second page, which greets the visitor by name. 84 web2py complete reference manual, 5th edition Write the corresponding actions in the default controller: 1 2 def first(): return dict() 3 4 5 def second(): return dict() Then create a view "default/first.html" for the first action, and enter: 1 2 3 4 5 6 {{extend 'layout.html'}}

Finally, create a view "default/second.html" for the second action: 1 2 {{extend 'layout.html'}}

# Hello {{=request.vars.visitor_name}}

In both views we have extended the basic "layout.html" view that comes with web2py. The layout view keeps the look and feel of the two pages consistent. The layout file can be edited and replaced easily, since it mainly contains HTML code. If you now visit the first page, type your name: and submit the form, you will receive a greeting: overview 3.2.5 85 Postbacks The mechanism for form submission that we used before is very common, but it is not good programming practice. All input should be validated and, in the above example, the burden of validation would fall on the second action. Thus the action that performs the validation is different from the action that generated the form. This tends to cause redundancy in the code. A better pattern for form submission is to submit forms to the same action that generated them, in our example the "first". The "first" action should receive the variables, process them, store them server-side, and redirect the visitor to the "second" page, which retrieves the variables. This mechanism is called a postback. Modify the default controller to implement self-submission: 1 2 def first(): if request.vars.visitor_name: 86 3 4 5 web2py complete reference manual, 5th edition session.visitor_name = request.vars.visitor_name redirect(URL('second')) return dict() 6 7 8 def second(): return dict() Then modify the "default/first.html" view: 1 2 3 4 5 6 {{extend 'layout.html'}} What is your name?
and the "default/second.html" view needs to retrieve the data from the session instead of from the request.vars: 1 2 {{extend 'layout.html'}}

# Hello {{=session.visitor_name or "anonymous"}}

From the point of view of the visitor, the self-submission behaves exactly the same as the previous implementation. We have not added validation yet, but it is now clear that validation should be performed by the first action. This approach is better also because the name of the visitor stays in the session, and can be accessed by all actions and views in the application without having to be passed around explicitly. Note that if the "second" action is ever called before a visitor name is set, it will display "Hello anonymous" because session.visitor_name returns None. Alternatively we could have added the following code in the controller (inside the second function): 1 2 if not request.function=='first' and not session.visitor_name: redirect(URL('first')) This is an ad hoc mechanism that you can use to enforce authorization on controllers, though see Chapter 9 for a more powerful method. With web2py we can move one step further and ask web2py to generate the form for us, including validation. web2py provides helpers (FORM, INPUT, TEXTAREA, and SELECT/OPTION) with the same names as the equivalent HTML tags. They can be used to build forms either in the controller or in the view. overview 87 For example, here is one possible way to rewrite the first action: 1 2 3 4 5 6 7 def first(): form = FORM(INPUT(_name='visitor_name', requires=IS_NOT_EMPTY()), INPUT(_type='submit')) if form.process().accepted: session.visitor_name = form.vars.visitor_name redirect(URL('second')) return dict(form=form) where we are saying that the FORM tag contains two INPUT tags. The attributes of the input tags are specified by the named arguments starting with underscore. The requires argument is not a tag attribute (because it does not start by underscore) but it sets a validator for the value of visitor_name. Here is yet another better way to create the same form: 1 2 3 4 5 6 7 8 def first(): form = SQLFORM.factory(Field('visitor_name', label='what is your name?', requires=IS_NOT_EMPTY())) if form.process().accepted: session.visitor_name = form.vars.visitor_name redirect(URL('second')) return dict(form=form) The form object can be easily serialized in HTML by embedding it in the "default/first.html" view. 1 2 {{extend 'layout.html'}} {{=form}} The form.process() method applies the validators and returns the form itself. The form.accepted variable is set to True if the form was processed and passed validation. If the self-submitted form passes validation, it stores the variables in the session and redirects as before. If the form does not pass validation, error messages are inserted into the form and shown to the user, as below: 88 web2py complete reference manual, 5th edition In the next section we will show how forms can be generated automatically from a model. In all our examples we have used the session to pass the user name from the first action to the second. We could have used a different mechanism and passed data as part of a redirect URL: 1 2 3 4 5 6 def first(): form = SQLFORM.factory(Field('visitor_name', requires=IS_NOT_EMPTY())) if form.process().accepted: name = form.vars.visitor_name redirect(URL('second',vars=dict(name=name))) return dict(form=form) 7 8 9 10 def second(): name = request.vars.visitor_name or redirect(URL('first')) return dict(name=name) Mind that in general it is not a good idea to pass data from one action to another using the URL. It makes it harder to secure the application. It is safer to store the data in a session. 3.2.6 Internationalization Your code is likely to include hardcoded strings such as "What is your name?". You should be able to customize strings without editing the code and in particular insert translations for these strings in different languages. overview 89 In this way if a visitor has the language preference of the browser set to "Italian", web2py will use the Italian translation for the strings, if available. This feature of web2py is called "internationalization" and it is described in more detail in the next chapter. Here we just observe that in order to use this feature you should markup strings that needs translation. This is done by wrapping a quoted string in code such as 1 "What is your name?" with the T operator: 1 T("What is your name?") You can also mark for translations strings hardcoded in views. For example 1

becomes 1

# Current Images

{{for image in images:}} {{=LI(A(image.title, _href=URL("show", args=image.id)))}} {{pass}}
The first thing to notice is that a view is pure HTML with special {{...}} tags. The code embedded in {{...}} is pure Python code with one caveat: indentation is irrelevant. Blocks of code start with lines ending in colon (:) and end in lines beginning with the keyword pass. In some cases the end of a block is obvious from context and the use of pass is not required. Lines 5-7 loop over the image rows and for each row image display: 1 LI(A(image.title, _href=URL('show', args=image.id)) This is a
• ...
• tag that contains an ... tag which contains the image.title. The value of the hypertext reference (href attribute) is: 1 URL('show', args=image.id) 100 web2py complete reference manual, 5th edition i.e., the URL within the same application and controller as the current request that calls the function called "show", passing a single argument to the function, args=image.id. LI, A, etc. are web2py helpers that map to the corresponding HTML tags. Their unnamed arguments are interpreted as objects to be serialized and inserted in the tag’s innerHTML. Named arguments starting with an underscore (for example _href) are interpreted as tag attributes but without the underscore. For example _href is the href attribute, _class is the class attribute, etc. As an example, the following statement: 1 {{=LI(A('something', _href=URL('show', args=123))}} is rendered as: 1
• something

# Image: {{=image.title}}

{{=post.author}} says {{=post.body}}

{{pass}}

overview 12 13 14 15 16 103 {{else:}}

{{pass}}

## Management Interface

of links to wiki pages""" query = db.page.title.contains(request.vars.keyword) pages = db(query).select(orderby=db.page.title) links = [A(p.title, _href=URL('show',args=p.id)) for p in pages] return UL(*links) Lines 2-6 constitute a comment for the index action. Lines 4-5 inside the comment are interpreted by python as test code (doctest). Tests can be run via the admin interface. In this case the tests verify that the index action runs without errors. Lines 18, 27, and 35 try to fetch a page record with the id in request.args(0). Lines 13, 20 define and process create forms for a new page and a new comment and 112 web2py complete reference manual, 5th edition Line 28 defines and processes an update form for a wiki page. Line 38 creates a grid object that allows to view, add and update the comments linked to a page. Some magic happens in line 51. The onkeyup attribute of the INPUT tag "keyword" is set. Every time the visitor releases a key, the JavaScript code inside the onkeyup attribute is executed, client-side. Here is the JavaScript code: 1 ajax('callback', ['keyword'], 'target'); is a JavaScript function defined in the file "web2py.js" which is included by the default "layout.html". It takes three parameters: the URL of the action that performs the synchronous callback, a list of the IDs of variables to be sent to the callback (["keyword"]), and the ID where the response has to be inserted ("target"). ajax As soon as you type something in the search box and release a key, the client calls the server and sends the content of the ’keyword’ field, and, when the sever responds, the response is embedded in the page itself as the innerHTML of the ’target’ tag. The ’target’ tag is a DIV defined in line 52. It could have been defined in the view as well. Here is the code for the view "default/create.html": 1 2 3 {{extend 'layout.html'}}

# Create new wiki page

{{=form}} Assuming you are registered and logged in, if you visit the create page, you see the following: overview Here is the code for the view "default/index.html": 1 2 3 4 5 6 7 {{extend 'layout.html'}}

# Available wiki pages

[ {{=A('search', _href=URL('search'))}} ]
{{for page in pages:}} {{=LI(A(page.title, _href=URL('show', args=page.id)))}} {{pass}}
[ {{=A('create page', _href=URL('create'))}} ] It generates the following page: Here is the code for the view "default/show.html": 113 114 1 2 3 4 5 6 7 8 9 10 11 12 web2py complete reference manual, 5th edition {{extend 'layout.html'}}

# {{=page.title}}

[ {{=A('edit', _href=URL('edit', args=request.args))}} | {{=A('documents', _href=URL('documents', args=request.args))}} ]
{{=MARKMIN(page.body)}}

{{=db.auth_user[post.created_by].first_name}} on {{=post.created_on}} says {{=post.body}}

{{pass}}

{{=form}} If you wish to use markdown syntax instead of markmin syntax: 1 from gluon.contrib.markdown import WIKI as MARKDOWN and use MARKDOWN instead of the MARKMIN helper. Alternatively, you can choose to accept raw HTML instead of markmin syntax. In this case you would replace: 1 {{=MARKMIN(page.body)}} with: 1 {{=XML(page.body)}} (so that the XML does not get escaped, which web2py normally does by default for security reasons). This can be done better with: 1 {{=XML(page.body, sanitize=True)}} By setting sanitize=True, you tell web2py to escape unsafe XML tags such as "') Un-escaped executable input such as this (for example, entered in the body of a comment in a blog) is unsafe, because it can be used to generate Cross Site Scripting (XSS) attacks against other visitors to the page. The web2py XML helper can sanitize our text to prevent injections and escape all tags except those that you explicitly allow. Here is an example: 1 2 >>> print XML('', sanitize=True) <script>alert("unsafe!")</script> The XML constructors, by default, consider the content of some tags and some of their attributes safe. You can override the defaults using the optional permitted_tags and allowed_attributes arguments. Here are the default values of the optional arguments of the XML helper. 236 1 2 3 4 5 web2py complete reference manual, 5th edition XML(text, sanitize=False, permitted_tags=['a', 'b', 'blockquote', 'br/', 'i', 'li', 'ol', 'ul', 'p', 'cite', 'code', 'pre', 'img/'], allowed_attributes={'a':['href', 'title'], 'img':['src', 'alt'], 'blockquote':['type']}) 5.2.2 Built-in helpers A This helper is used to build links. 1 2 3 >>> print A('', XML('me'), _href='http://www.web2py.com') <click>me/b> Instead of _href you can pass the URL using the example in a view: 1 callback argument. For {{=A('click me', callback=URL('myaction'))}} and the effect of pressing the link will be an ajax call to "myaction" instead of a redirection. In this case, optionally you can specify two more arguments: target and delete: 1 2 {{=A('click me', callback=URL('myaction'), target="t")}}
and the response of the ajax callback will be stored in the DIV with id equal to "t". 1
{{=A('click me', callback=URL('myaction'), delete='div#b")}}
and upon response, the closest tag matching "div#b" will be deleted. In this case, the button will be deleted. A typical application is: 1 {{=A('click me', callback=URL('myaction'), delete='tr")}} in a table. Pressing the button will perform the callback and delete the table row. callback and delete can be combined. The A helper takes a special argument called cid. It works as follows: 1 2 {{=A('linked page', _href='http://example.com', cid='myid')}}
the views 237 and a click on the link causes the content to be loaded in the div. This is similar but more powerful than the above syntax since it is designed to refresh page components. We discuss applications of cid in more detail in Chapter 12, in the context of components. These ajax features require jQuery and "static/js/web2py_ajax.js", which are automatically included by placing {{include ’web2py_ajax.html’}} in the layout head. "views/web2py_ajax.html" defines some variables based on request and includes all necessary js and css files. B This helper makes its contents bold. 1 2 >>> print B('', XML('world'), _class='test', _id=0) <hello>world BODY This helper makes the body of a page. 1 2 >>> print BODY('', XML('world'), _bgcolor='red') <hello>world BR This helper creates a line break. 1 2 >>> print BR()
Notice that helpers can be repeated using the multiplication operator: 1 2 >>> print BR()*5

CAT This helper concatenates other helpers, same as TAG[”]. 1 2 >>> print CAT('Here is a ', A('link',_href=URL()), ', and here is some ', B('bold text'), '.') Here is a link, and here is some bold text. CENTER This helper centers its content. 1 2 3 >>> print CENTER('', XML('world'), _class='test', _id=0) >>>
<hello>world
238 web2py complete reference manual, 5th edition CODE This helper performs syntax highlighting for Python, C, C++, HTML and web2py code, and is preferable to PRE for code listings. CODE also has the ability to create links to the web2py API documentation. Here is an example of highlighting sections of Python code. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 >>> print CODE('print "hello"', language='python').xml()  1 print "hello"
Here is a similar example for HTML 1 2 3 1 2 3 >>> print CODE( >>> '{{=request.env.remote_add}}', >>> language='html') ...... {{=request.env.remote_add}} ......
These are the default arguments for the CODE helper: 1 CODE("print 'hello world'", language='python', link=None, counter=1, styles={}) Supported values for the language argument are "python", "html_plain", "c", "cpp", "web2py", and "html". The "html" language interprets {{ and }} tags as "web2py" code, while "html_plain" doesn’t. If a link value is specified, for example "/examples/global/vars/", web2py API references in the code are linked to documentation at the link URL. the views 239 For example "request" would be linked to "/examples/global/vars/request". In the above example, the link URL is handled by the "vars" action in the "global.py" controller that is distributed as part of the web2py "examples" application. The counter argument is used for line numbering. It can be set to any of three different values. It can be None for no line numbers, a numerical value specifying the start number, or a string. If the counter is set to a string, it is interpreted as a prompt, and there are no line numbers. The styles argument is a bit tricky. If you look at the generated HTML above, it contains a table with two columns, and each column has its own style declared inline using CSS. The styles attributes allows you to override those two CSS styles. For example: 1 {{=CODE(...,styles={'CODE':'margin: 0;padding: 5px;border: none;'})}} The attribute must be a dictionary, and it allows two possible keys: for the style of the actual code, and LINENUMBERS for the style of the left column, which contains the line numbers. Mind that these styles completely replace the default styles and are not simply added to them. styles CODE COL 1 2 >>> print COL('a','b') ab COLGROUP 1 2 >>> print COLGROUP('a','b') ab DIV All helpers apart from XML are derived from DIV and inherit its basic methods. 1 2 >>> print DIV('', XML('world'), _class='test', _id=0)
<hello>world
EM Emphasizes its content. 1 2 >>> print EM('', XML('world'), _class='test', _id=0) <hello>world FIELDSET This is used to create an input field together with its label. 240 1 2 web2py complete reference manual, 5th edition >>> print FIELDSET('Height:', INPUT(_name='height'), _class='test')
Height:
FORM This is one of the most important helpers. In its simple form, it just makes a
...
tag, but because helpers are objects and have knowledge of what they contain, they can process submitted forms (for example, perform validation of the fields). This will be discussed in detail in Chapter 7. 1 2 3 >>> print FORM(INPUT(_type='submit'), _action='', _method='post')
The "enctype" is "multipart/form-data" by default. The constructor of a FORM, and of SQLFORM, can also take a special argument called hidden. When a dictionary is passed as hidden, its items are translated into "hidden" INPUT fields. For example: 1 2 3 >>> print FORM(hidden=dict(a='b'))
H1, H2, H3, H4, H5, H6 These helpers are for paragraph headings and subheadings: 1 2 >>> print H1('', XML('world'), _class='test', _id=0)

# <hello>world

HEAD For tagging the HEAD of an HTML page. 1 2 >>> print HEAD(TITLE('', XML('world'))) <hello><b>world</b> HTML This helper is a little different. In addition to making the prepends the tag with a doctype string [61, 62, 63]. 1 2 3 4 tags, it >>> print HTML(BODY('', XML('world'))) <hello>world The HTML helper also takes some additional optional arguments that have the following default: the views 1 241 HTML(..., lang='en', doctype='transitional') where doctype can be ’strict’, ’transitional’, ’frameset’, ’html5’, or a full doctype string. XHTML XHTML is similar to HTML but it creates an XHTML doctype instead. 1 XHTML(..., lang='en', doctype='transitional', xmlns='http://www.w3.org/1999/xhtml') where doctype can be ’strict’, ’transitional’, ’frameset’, or a full doctype string. HR This helper creates a horizontal line in an HTML page 1 2 >>> print HR()
I This helper makes its contents italic. 1 2 >>> print I('', XML('world'), _class='test', _id=0) <hello>world INPUT Creates an tag. An input tag may not contain other tags, and is closed by /> instead of >. The input tag has an optional attribute _type that can be set to "text" (the default), "submit", "checkbox", or "radio". 1 2 >>> print INPUT(_name='test', _value='a') It also takes an optional special argument called "value", distinct from "_value". The latter sets the default value for the input field; the former sets its current value. For an input of type "text", the former overrides the latter: 1 2 >>> print INPUT(_name='test', _value='a', value='b') For radio buttons, INPUT selectively sets the "checked" attribute: 1 2 3 4 >>> for v in ['a', 'b', 'c']: >>> print INPUT(_type='radio', _name='test', _value=v, value='b'), v a b 242 5 web2py complete reference manual, 5th edition c and similarly for checkboxes: 1 2 3 4 >>> print INPUT(_type='checkbox', _name='test', _value='a', value=True) >>> print INPUT(_type='checkbox', _name='test', _value='a', value=False) IFRAME This helper includes another web page in the current page. The url of the other page is specified via the "_src" attribute. 1 2 >>> print IFRAME(_src='http://www.web2py.com') IMG It can be used to embed images into HTML: 1 2 >>> IMG(_src='http://example.com/image.png',_alt='test') Here is a combination of A, IMG, and URL helpers for including a static image with a link: 1 2 3 4 5 >>> A(IMG(_src=URL('static','logo.png'), _alt="My Logo"), _href=URL('default','index')) LABEL It is used to create a LABEL tag for an INPUT field. 1 2 >>> print LABEL('', XML('world'), _class='test', _id=0) LEGEND It is used to create a legend tag for a field in a form. 1 2 >>> print LEGEND('Name', _for='myfield') Name LI It makes a list item and should be contained in a UL or OL tag. 1 2 >>> print LI('', XML('world'), _class='test', _id=0)
• <hello>world
• the views 243 META To be used for building META tags in the HTML head. For example: 1 2 >>> print META(_name='security', _content='high') MARKMIN Implements the markmin wiki syntax. It converts the input text into output html according to the markmin rules described in the example below: 1 2 3 >>> print MARKMIN("this is **bold** or ''italic'' and this [[a link http://web2py. com]]")

this is bold or italic and this a link

The markmin syntax is described in this file that ships with web2py: 1 http://127.0.0.1:8000/examples/static/markmin.html You can use markmin to generate HTML, LaTeX and PDF documents: 1 2 3 4 5 6 7 m = "Hello **world** [[link http://web2py.com]]" from gluon.contrib.markmin.markmin2html import markmin2html print markmin2html(m) from gluon.contrib.markmin.markmin2latex import markmin2latex print markmin2latex(m) from gluon.contrib.markmin.markmin2pdf import markmin2pdf print markmin2pdf(m) # requires pdflatex (the MARKMIN helper is a shortcut for markmin2html) Here is a basic syntax primer: 244 web2py complete reference manual, 5th edition SOURCE ”italic” OUTPUT title section subsection bold italic “verbatim“ verbatim http://google.com http://google.com http://... http:... http://...png http://...mp3 http://...mp4 qr:http://... embed:http://... [[click me #myanchor]] click me Rb a sin ( x ) dx # title ## section ### subsection **bold** $$\int_ab̂ sin(x)dx$$ Simply including a link to an image, a videos or an audio files without markup result in the corresponding image, video or audio file being included automatically (for audio and video it uses html