2.9.6 - 2.9.10

  • fixed support of GAE + SQL
  • fixed a typo in the license of some login_methods code. It is now LGPL consistently with the rest of the web2py code. This change applied to all previous web2py versions.
  • support for SAML2 (with pysaml2)
  • Sphinx documentation (thanks Niphlod)
  • improved scheduler (thanks Niphlod)
  • increased security
  • better cache.disk (thanks Leonel)
  • sessions are stored in subfolders for speed
  • postgres support for "INSERT ... RETURING ..."
  • ldap support for Certificate Authority (thanks Maggs and Shane)
  • improved support for S/Mime X.509 (thanks Gyuris)
  • better welcome app
  • support for Collection+JSON Hypermedia API (RESTful self documenting API)
  • jQuery 1.11
  • codemirror 4.0.3
  • markdown2 2.2.3
  • memcache 1.53
  • support for the new janrain API
  • new "web2py.py -G config" to make GAE configuration easier
  • many small bug fixes

2.9.1 - 2.9.5

  • many small but important bug fixes
  • jquery 1.11
  • codemirror 3.21, thanks Paolo Valleri
  • fixed security issue with sessions in database, thanks Nathan Humphreys
  • fixed security issue with persistant data in session, thanks Kiran
  • fixed security issue with redirect after expired login, thanks André Kablu
  • cleaner DAL and rname integration, thanks niphlod and Michele
  • added mongodb and imap tests for dal, thanks Alan
  • NoSQL dal tests, thanks Alan
  • better docstrings, thanks Niphlod
  • allow URL(...,language=...) with parametric router, thanks Jonathan
  • allow non-expiration of gae-memcache, thanks crimsoncantab
  • MARKMIN(...,_class='...'), thanks Luca
  • better transliteration in building slugs
  • autolink emails
  • new Janrain API, thanks PeterQ2
  • enable admin app for GAE (experimental), thanks Alan
  • many bug fixes
  • invalidate function in web2py.js, thanks Paolo
  • DAL(...,adapter_args=dict(engine='MyISAM'))
  • todolist panel in admin editor, thanks Paolo Valleri


  • no more winservice (use nssm instead)
  • better imap support in DAL
  • db().select().as_tree()
  • bootstrap 2.3.2
  • codemirror 3.19
  • improved mongoDB support, thanks Alan
  • support for wiki custom render function
  • Wiki(...groups=['x','y']) allows bypassing default permissions
  • fixed websocket_messaging.py to support newer Tornado
  • NDB support for GAE, thanks Quint
  • fixed major concurrecy issue with MEMDB
  • blocked generic.jsonp for security reasons
  • many bug fixes, thanks Niphlod, Michele, Anthony, Tim, and many others.

2.7.1 - 2.7.4

  • jQuery 1.10.2
  • codemirror 3.18, thanks Paolo
  • namespaces in T("Welcome", ns="namespace"), thanks jamarcer (experimental)
  • more Auth options, thanks Charles
  • more admin configuration, thanks Roberto
  • new gluon.contrib.strip.StripeForm for PCI compliant payments
  • webclient can hendle lists, thanks Yair
  • allows SQLFORM.grid(...,ignore_common_filters=True)
  • more translations, thanks Vladyslav
  • better session2trash.py, works with scheduler, thanks niphlod
  • fixed problem with ENABLED/DISABLED
  • many bug fixes, thanks niphlod, michele, anthony, roberto, tim, and others

2.6.1 - 2.6.4

Attention all users: For pre 2.6 applications to work with web2py >=2.6, you must copy static/js/web2py.js, controllers/appadmin.py, and views/appadmin.html from the welcome app to your own apps (all of them).

Attention production users: The updated handlers and examples are in handlers/ and examples/. The updated ones will not override the existing ones. To use the new ones it is not sufficient to upgrade web2py, you also need to copy the desired handler/example in the root web2py/ folder.

Attention MySQL users: The length of string fields changed from 255 to 512 bytes. If you have migrations enabled this will trigger a large migration. To prevent it, first set migrate_enabled=False, upgrade, check everything is ok, then add length=255 to your string Fields, then re-enable migrations with migrate_enabled=True if needed.

  • better directory structure: handlers/ extras/ examples/
  • better MongoDb support, thanks Alan
  • better Admin editor interface, thanks Paolo, Roberto (codemirror 3), and Lightdot
  • better layout.html and web2py_bootstrap.css, thanks Paolo
  • refactored web2py.js makes code more readable, thanks Niphlod
  • compute fields can depend on other compute(d) fields
  • more functions in appadmin (/manage/auth), thanks Anthony
  • support for CAST in SQL generation
  • new API jQuery('#component').reload()
  • new API rows.render()
  • new API table.field.referent, table._references
  • new API db(...).validate_and_update(...)
  • new API Wiki(..., force_render=True) renders the page source again instead of using cached
  • Wiki now automatically parses named component arguments @{f:a=1,b='twp',c=variable}
  • auth.get_or_create_user(login=False)
  • auth = Auth(crsf_protection = False) prevents creating sessions in login/register forms.
  • enable multiple renderers in wiki, thanks Alan
  • log messages from Auth are no longer translated (for speed and readability)
  • update jQuery mobile to 1.3.1
  • reduced memory footprint by conditionally loading Tk
  • faster pbkdf2 uses OpenSSL, thanks Michele
  • many speed improvements, thanks Michele
  • better session logic, prevents false positive when detecting session changes.
  • scripts/import_static.py converts a static site to a web2py app (experimental)
  • support for new http error code 451
  • profiler saves dump in dir, thanks Niphlod
  • upgraded pyfpdf, thanks Mariano
  • gluon/contrib/pdfinvoice.py for generating PDF invoices (assumes reportlab)
  • no more double submission of forms (even without crsf protection), thanks Niphlod
  • speedup for define_table, thanks Michele
  • settings.cfg to admin, thanks Paolo
  • many bugs fixed, thanks Niphlod, Michele, Roberto, Jonathan, and many others
  • 2.6,3 specifically fixed a possible DoS vulnerability
  • 2.6.4 specifically fixes major problem introduced in 2.6.1 with session logic


  • Web editor with tabs, thanks ilvalle


  • New style virtual fields in grid
  • Conditional fields (experimental) db.table.field.show_if = db.table.otherfield==True or db.table.field.show_if = db.table.otherfiel.contains(values)
  • auth.settings.manager_group_role="manager" enables http://.../app/appadmin/auth_manage and http://.../app/appadmin/manage for members of the "manager" group. (also experimental)
  • support for POST variables in DELETE
  • Fixed memory leak when using the TAG helper


  • pypy support, thanks Niphlod
  • more bug fixes
  • ...


  • better tests
  • new ANY_OF and IS_IPV6 validators
  • new custom save option
  • many small bug fixes


  • travis.ci integration (thanks Marc Abramowitz and Niphlod). Passes all tests (thanks Niplod).
  • IS_DATE and IS_DATETIME can specify timezone

2.4.1- 2.4.3

  • 2D GEO API: geoPoint, getLine, geoPolygon
  • support for 'json' field type in DAL
  • schema export with db.as_json/as_xml, thanks Alan
  • graph representation of models
  • support for semantic versioning
  • new bootstrap based admin, thanks Paolo
  • improved scheduler (and change in scheduler field names), thanks Niphlod
  • graphviz support added to adm, thanks Jose
  • on_failure in grid
  • db.table.field.abs()
  • better wiki
  • geoPoint, getLine, geoPolygon
  • better reporting of 500 ajax errors
  • better grid
  • improved/fixed mongodb support
  • improved parse_as_rest(patterns=...), thanks Denes
  • improved IMAP DAL support, thanks Alan
  • improved security when cookies in sessions
  • Row.as_xml, as_json, as_dict, as_yaml thanks Alan
  • smarter custom_import
  • setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
  • added support for motor and pulsar servers, thanks Niphlod
  • added json-rpc2 support
  • added pypyodbc.py driver
  • allow auth.settings.ondelete='CASCADE'
  • new syntax IS_EXPR(lambda value: ...
  • using google for QR codes (although Graph API will be deprecated in 2015)
  • upgraded fpdf to 1.7.1
  • bug fixes (including issues with calendar.js and archive tables)

2.3.1 - 2.3.2

  • new virtual fields syntax: db.define_table('person',Field('name'),Field.Virtual('namey',lambda row: row.person.name+'y'))
  • db.thing(name='Cohen',_orderby=db.thing.name), thanks Yair
  • made many modules Python 3.3 friendly (compile but not tested)
  • better welcome css, thanks Paolo
  • jQuery 1.8.3
  • Bootstrap 2.2.2
  • Modernizr 2.6.2 (custom full options)
  • integration with analyitics.js (0.2.0)
  • better scheduler, thanks Niphlod
  • page and media preview in wiki, thanks Niphlod
  • create new auth.wiki page from slug model, thanks Nico
  • conditional menus with auth.wiki(menugroups=['wiki_editor'])
  • better security in grid/smartgrid
  • allow LOADing multiple grids, thanks Niphlod
  • auth.settings.login_onfail, thanks Yair
  • better handling of session files for speed
  • added heroku support (experimental)
  • added rocket support for IPV6, thanks Chirs Winebrinner
  • more customizable menus with MENU(li_first, li_last..)
  • added support for paymentech (gluon/contrib/paymentech.py)
  • fixed broken cron
  • fixed possible xss with share.js
  • many bug fixes. Closed more than 50 tickets since 2.2.1


  • session.connect(cookie_key='secret', compression_level=9) stores sessions in cookies
  • T.is_writable = False prevents T from dynamically updating langauge files
  • all code is more PEP8 compliant
  • better custom_importer behaviour (now works per app, is smalled and faster)
  • fixed some bugs
  • upgraded feedparser.py and rss2.py
  • codemirror has autoresize


  • overall faster web2py
  • when apps are deleted, a w2p copy is left in deposit folder
  • change in cron (it is now disabled by default). removed -N option and introduced -Y.
  • faster web2py_uuid() and request initialization logic, thanks Michele
  • static asset management, thanks Niphlod
  • improved mobile admin
  • request.requires_https and Auth(secure=True), thanks Yarin and Niphlod
  • better custom_import (works per app and is faster), thanks Michele
  • redis_sesssion.py, thanks Niphlod
  • allow entropy computation in IS_STRONG and web2py.js, thanks Jonathan and Niphlod
  • fixed many aith.wiki problems
  • support for auth.wiki(render='html')
  • better welcome layout, thanks Paolo
  • db.define_table(...,redefine=True)
  • DAL, Row, and Rows object can now be pickled/unpickled, thanks to zombie DAL.
  • admin uses codemirror
  • allow syntax auth = Auth(db).define_tables()
  • better auth.wiki with preview, thanks Alan
  • better auth.impersonate, thanks Alan
  • upgraded jQuery 1.8
  • upgraded Bootstrap 2.1
  • fixed problem with dropbox_account.py
  • many fixes to cache.ram, cache.disk, memcache and gae_memcache
  • cache.with_prefix(cache.ram,'prefix')
  • db.table.field.epoch() counts seconds from epoch
  • DAL support for SQL CASE, example: db().select(...query.case('true','false))
  • DAL(...,do_connect=False) allows faking connections
  • DAL(...,auto_import=True) now retieves some fiel attributes
  • mail can specify a sender: mail.send(...,sender='Mr X <%(sender)s>')
  • renamed gluon/contrib/comet_messaging.py -> gluon/contrib/websocket_messaging.py


DAL Improvements

  • Support for DAL(lazy_tables=True) and db.define_table(on_define=lambda table:), thanks Jonathan
  • db(...).select(cacheable=True) make select 30% faster
  • db(...).select(cache=(cache.ram,3600)) now caches parsed data 100x faster
  • db(...).count(cache=(cache.ram,3600)) now supported
  • MongoDB support in DAL (experimental), thanks Mark Breedveld
  • geodal and spatialite, thanks Denes and Fran (experimental)
  • db.mytable._before_insert, _after_insert, _before_update, _after_update, _before_delete. _after_delete (list of callbacks)
  • db(...).update_naive(...) same as update but ignores table._before_update and table._after_update
  • DAL BIGINT support and DAL(...,bigint_id=True)
  • IS_IN_DB(..., distinct=True)
  • new syntax: db.mytable.insert(myuploadfield=open(....)), thank you Iceberg
  • db(...).select(db.mytable.myfield.count(distinct=True))
  • db(db.a)._update(name=db(db.b.a==db.a.id).nested_select(db.b.id))
  • db.mytable.myfield.filter_in, filter_out
  • db.mytable._enable_record_versioning(db) adds versioning to this table
  • teradata adapter, thanks Andrew Willimott
  • experimental Sybase Adapter
  • added db.table.field.avg()
  • Support for Google App Engine projections, thanks Christian
  • Field(... 'upload', default=path) now accepts a path to a local file as default value, if user does not upload a file. Relative path looks inside current application folder, thanks Marin
  • executesql(...,fields=,columns=) allows parsing of results in Rows, thanks Anthony
  • Rows.find(lambda row: bool(), limitby=(0,1))

Auth improvements

  • auth.enable_record_versioning(db) adds full versioning to all tables
  • @auth.requires_login(otherwise=URL(...))
  • auth supports salt and compatible with third party data, thanks Dave Stoll
  • CRYPT now defaults to pbkdf2(1000,20,sha1)
  • Built-in wiki with menu, tags, search, media, permissions. def index: return auth.wiki()
  • auth.settings.everybody_group_id
  • allow storage of uploads on any PyFileSystem (including amazon)

Form improvements

  • FORM.confirm('Are you sure?',{'Back':URL(...)})
  • SQLFORM.smartdictform(dict)
  • form.add_button(value,link)
  • SQLFORM.grid(groupby='...')
  • fixed security issue with SQLFORM.grid and SQLFORM.smartgrid
  • more export options in SQLFORM.grid and SQLFORM.smartgrid (html, xml, csv, ...)

Admin improvements

  • new admin pages: manage_students, bulk_regsiter, and progress reports
  • increased security in admin against CSRF
  • experimental Git integration
  • experimental OpenShift deployment
  • multi-language pluralization engine
  • ace text web editor in admin
  • Ukrainian translations, thanks Vladyslav Kozlovskyy
  • Romanian translation for welcome, thanks ionel
  • support for mercurial 2.6, thanks Vlad

Scheduler Improvements (thanks to niphlod, ykessler, dhx, toomim)

  • web2py.py -K myapp -X starts the myapp scheduler alongside the webserver
  • tasks are marked EXPIRED (if stop_time passed)
  • functions with no result don't end up in scheduler_run
  • more options: web2py.py -E -b -L
  • scheduler can now handle 10k tasks with 20 concurrent workers and with no issues
  • new params: tasks can be found in the environment (no need to define the tasks parameter) max_empty_runs kills the workers automatically if no new tasks are found in queue (nice for "spikes" of processing power) discard_results to completely discard the results (if you don't need the output of the task) utc_time enables datetime calculations with UTC time
  • scheduler_task changes: task_name is no longer required (filled automatically with function_name if found empty) uuid makes easy to coordinate scheduler_task maintenance (filled automatically if not provided) stop_time has no default (previously was today+1) retry_failed to requeue automatically failed tasks sync_output refreshes automatically the output (nice to report percentages)
  • workers can be: DISABLED (put to sleep and do nothing if not sending the heartbeat every 30 seconds) TERMINATE (complete the current task and then die) KILL (kill ASAP)

Other Improvements

  • gluon/contrib/webclient.py makes it easy to create functional tests for app
  • DIV(..).elements(...replace=...), thanks Anthony
  • new layout based on Twitter Bootstrap
  • New generic views: generic.ics (Mac Mail Calendar) and generic.map (Google Maps)
  • request.args(0,default=0, cast=int, otherwise=URL(...)), thanks Anthony
  • redirect(...,type='auto') will be handled properly in ajax responses
  • routes in can redirect outside with routes_in=[('/path','303->http://..')]
  • better memcache support
  • improved spreadsheet, thanks Alan
  • new internationalization engine, thanks Vladyslav
  • pluralization engine, thanks Vladyslav
  • new markmin with support for nested lists, <i>, <em>, autolinks, thanks Vladyslav
  • new syntax: {{=BR()*5}}
  • gluon.cache.lazy_cache decorator allows caching functions in modules
  • .coffee and .less support in response.files, thanks Sam Sheftel
  • ldap certificate support
  • pg8000 postgresql driver support (experimental)
  • @cache('%(name)s%(args)s%(vars)s',5) and cache.autokey
  • added tox.ini, thanks Marc
  • web2py.py --run_system_tests, thanks Marc Abramowitz
  • html.py (and web2py helpers) can be used without web2py dependencies
  • new fpdf, thanks Mariano


  • admin in Russian (Bulat), Japanese (Omi) and Slovenian (Robert Valentak)
  • included web-based debugger (experimental, thanks Mariano)
  • def index(): return dict(a=gluon.tools.Expose(folder))
  • db.table.field.like(...,case_sensitive=False) (thanks Floyd)
  • db.table.field.regexp(...) for sqlite and postgres
  • db(...,ignore_common_filters=True)
  • db(db.dog_id.belongs(db.dogs.owner=='james')).select()
  • db(...).select().group_by_value(db.table.field) (thanks Yair)
  • db = DAL('imap://user:password@server:port') support (thanks Alan Etkin)
  • db = DAL('teradata://DSN=dsn;UID=user;PWD=pass; DATABASE=database') (thanks Adrew Willmott)
  • db = DAL('mongodb://') (experimental, thanks Mark Breedveld)
  • db = DAL('cubrid') (experimental)
  • db = DAL('postgres:pg8000:...') and DAL('postgres:psycopg2:...')
  • pg8000 now ships with web2py (thanks Mariano)
  • reponse.delimiters = ('\[','\]') (thanks Denes)
  • auth.user_groups stores user groups
  • auth.is_impersonating()
  • populate can now deal with computed fields (thanks Tsvi Mostovicz)
  • new rediscache (thanks niphold)
  • sync languages capability (thanks Yair)
  • improved markmin auto-links
  • improved ldap support (thanks Omi)
  • added TimeCollector (thanks Caleb)
  • better cpdb.py (thanks pasxidis)
  • conditional menu items (reponse.menu=[(title,bool,link,[],condition)]
  • scripts/services/service.py (thanks Ross)
  • gluon/contrib/login_methods/browserid_account.py (thanks Pai)
  • gluon/contrib/htmlmin.py for html minimization (thanks kerncece)
  • web2py_component has timeout parameter, thanks Alan
  • 100's of small bug fixes and small improvements


Improved mobile admin, thanks Angelo Improved examples page, thanks Anthony fixed a SQLCustomField bug


This is a major revision in peparation for web2py 2.0

  • moved to GitHub and abandoned Lanchpad
  • new web site layout, thanks Anthony
  • new welcome app using skeleton, thanks Anthony
  • jQuery 1.7.1
  • modernizr 2.0.6 (customized)
  • define_table('thing', singluar='thing',plural='things')
  • CAS 1.0 and 2.0 compliant, thanks Olivier
  • fixed validate_and_insert and validate_and_update, thanks Anthony
  • request.user_agent().is_mobile etc., thanks Ross and Angelo
  • better router, thanks Jonathan
  • app on/off buttons
  • support for dropbox_login
  • improved markmin recognizes qr code, supports auto audio/video/embed
  • response.optimize_css = 'concat,minify,inline', thanks Ross
  • response.optimize_js = 'concat,minify,inline' thanks Ross
  • db.define_table(...,common_filter=query), thanks Yair
  • db(...,ignore_common_filter=True)
  • support for stripe payments
  • support for DowCommerce payments, thanks Dave
  • experimental PyPy support
  • experimental mongodb support, thanks Mark
  • tickets in db now accessible from admin, thanks Niphlod


  • gluon/contrib/simplejsonrpc.py
  • gluon/contrib/redis_cache.py
  • support for A(name,callback=url,target='id',delete='tr')
  • support for A(name,component=url,target='id',delete='tr')
  • new pip installer, thanks Chris Steel
  • isapiwsgihandler.py
  • dal expression.coalesce(*options)
  • gluon/contrib/simplejsonrpc.py, thanks Mariano
  • expire_sessions.py respects expiration time, thanks iceberg
  • addressed this issue: http://fuelyourcoding.com/jquery-events-stop-misusing-return-false/
  • x509 support (thanks Michele)
  • form.process() and for.validate()
  • rocket upgrade (1.2.4)
  • jQuery upgrade (1.6.3)
  • new syntax rows[i]('tablename.fieldname')
  • new query syntax field.contains(list,all=True or False)
  • new SQLFORM.grid and SQLFORM.smartgrid (should replace crud.search and crud.select)
  • support for natural language queries (english only) in SQLFORM.grid
  • support for computed columns and additional links in SQLFORM.grid
  • new style virtual fields (experimental): db.table.field=Field.Lazy(...)
  • request.utcnow
  • cleaner/simpler welcome/models/db.py and welcome layout.html
  • response.include_meta() and response.include_files(), thanks Denes
  • dal auto-reconnect on time-out connections
  • COL and COLGROUP helpers
  • addresed OWASP #10, thanks Anthony and Eric
  • auth.settings.login_after_registration=True
  • detection of mobile devices and @mobilize helper (view.mobile.html), thanks Angelo
  • experimental gluon/scheduler.py
  • scripts/make_min_web2py.py
  • crud.search has more options, thanks Denes
  • many bug fixes (thanks Jonathan, Michele, Fran and others)


  • fixed some problems with LOAD(ajax=False), thanks Anthony
  • jquery 1.6.2
  • gevent.pywsgi adds ssl support, thanks Vasile
  • import/export of blobs are base64 encoded
  • max number of login attemts in admin, thanks Ross
  • fixed joins with alias tables
  • new field.custom_delete attribute
  • removed resctions on large 'text fields, thanks Martin
  • field.represent = lambda value,record: .... (record is optional)
  • FORM.validate() and FORM.process(), thanks Bruno
  • faster visrtualfields, thanks Howsec
  • mail has ssl support separate from tls, thanks Eric
  • TAG objects are now pickable
  • new CAT tag for no tags
  • request.user_agent(), thanks Ross
  • fixed fawps support
  • SQLFORM(...,separator=': ') now customizable
  • many small bug fixes


  • validate_and_update, thanks Bruno
  • fixed problem with new custom import, thanks Mart
  • fixed pyamf 0.6, thanks Alexei and Nickd
  • fixed "+ =" bug in wizard
  • fixed problem with allowed_patterns
  • fixed problems with LOAD and vars and ajax
  • closed lots of google code tickets
  • checkboxes should now work with list:string
  • web2py works on Android, thanks Corne Dickens
  • new cpdb.py, thanks Mart
  • improved translation (frech in particuler), thanks Pierre
  • improved cas_auth.py, thanks Sergio
  • IS_DATE and IS_DATETIME validators now work with native types
  • better description of --shell, thanks Anthony
  • extra SQLTABLE columns, thanks Martin
  • fixed toolbar conflics, thanks Simon
  • GAE password shows with ****


  • bug fixes


  • "from gluon import *" imports in every python module a web2py environment (A, DIV,..SQLFORM, DAL, Field,...) including current.request, current.response, current.session, current.T, current.cache, thanks Jonathan.
  • conditional models in models/<controller>/a.py and models/<controller>/<function>/a.py
  • from mymodule import *, looks for mymodule in applications/thisapp/modules first and then in sys.path. No more need for local_import. Thanks Pierre.
  • usage of generic.* views is - by default - restricted to localhost for security. This can be changed in a granular way with: response.generic_patterns=['*']. This is a slight change of behavior for new app but a major security fix.
  • all applications have cas 2.0 provider at http://.../user/cas/login
  • all applications can delegate to login to external provider Auth(...,cas_provider='http://.../other_app/default/user/cas')
  • A(...,callback=URL(...),larget='id') does Ajax
  • URL(...,user_signature=True), LOAD(...,user_signature=True) can sign urls and @auth.requires_signature() will check the signature for any decorated action.
  • DAL(...,migrate_enabled=False) to disable all migrations
  • DAL(...,fake_migrate_all=True) to rebuild all corrupted metadata
  • new DAL metadata format (databases/*.table)
  • DAL(...,adapter_arg={}) allows support for alternate drivers
  • DAL now allows circular table defintions
  • DAL(..,auto_import=True) automatically imports tables from metadata without need to db.define_table(...)s.
  • new alterante syntax for inner joins: db(...).select(join=...)
  • experimental cubrid database support
  • DAL 'request_tenant' fields are special, the altomatically filer all records based on their default value.
  • db._common_fields.append(Field('owner')) allows to add fields to ALL tables
  • DAL ignores repeated fields with same names
  • web2py_ajax.html is more modular, thanks Anthony
  • request.is_local
  • request.is_http
  • new sessions2trash.py thanks Jim Karsten
  • corrupted cache files are automatically deleted
  • new simpler API gluon.contrib.AuthorizeNet.procss(...)
  • fixed recaptcha (as they released new API)
  • messages in validators have default internationalization
  • No more Auth(globals(),db), just Auth(db). Same for Crud and Service.
  • scripts/access.wsgi allows apache+mod_wsgi to delegate authentication of any URL to any web2py app
  • json now supports T(...)
  • scripts/setup-web2py-nginx-uwsgi-ubuntu.sh
  • web2py HTTP responses now set: "X-Powered-By: web2py", thanks Bruno
  • mostly fixed generic.pdf. You can view any page in PDF if you have pdflatex installed or if your html follows the pyfpdf convention.
  • auth.settings.extra_fields['auth_user'].append(Field('country')) allows to extend auth_* tables without need of definiting a custom auth_* table. Must be placed before auth.define_tables()
  • {{=response.toolbar()}} to help you debug applications
  • web based shell now supports object modifications (but no redefinitions of non-serializable types)
  • jQuery 1.6.1
  • Lots of bug fixes


  • Google MySQL support (experimental)
  • pip support, thanks lifeeth
  • better setup_exe.py, thanks meredyk
  • importved pyfpdf
  • domain check in email_auth.py, thanks Gyuris
  • added change_password_onvalidation and change_password_onaccept
  • DAL(...,migrate_enabled=True)
  • login_methods/loginza.py, thanks Vladimir
  • bpython shell support, thanks Arun
  • request.uuid and response.uuid (for a future toolbar)
  • db._timings contains database query timing info
  • efficient db(...).isempty()
  • setup-web2py-nginx-uwsgi-ubuntu.sh
  • Many bug fixes, thanks Jonathan


  • fixed a number of minor bugs including adding some missing files
  • better session handling on session._unlock(..), thanks Jonathan
  • added experimental pip support, thanks Lifeeth
  • added experimental SAP DB support


  • fixed a major bug with session introdued in 1.94.1


  • removed debug print statement that caused problems on GAE and mod_wsgi


  • fixed major bug in auth redirection


  • reverted wrong behavior of auth.requires(condition) in 1.94.1


  • moderniz 1.17
  • web2py no longer saves session if no change, this makes it up up to 10x faster for simple actions
  • experimental REST API
  • better support for MSSQL NOT NULL
  • small bug fixes


  • support for multiple interfaces, thanks Jonathan
  • jquery 1.5.1
  • simplejson 2.1.3
  • customizable simplejson
  • leaner app.yaml
  • css3 buttons in welcome
  • android support (experimental)
  • Field(':hidden'), Field('.readonly'), Field('name=value')
  • combined expressions print db.data.body.len().sum()
  • wizard can download plugins
  • better json serilization (object.custom_json)
  • better xml serialization (object.custom_xml)
  • better formstyle support
  • better comet_messaging.py (needs more testing)
  • many bug fixes


  • much improved routing (thanks Jonathan)
  • Expression.__mod__ (thanks Denes)
  • admin has MULTI_USER_MODE (admin/models/0.py)
  • support for count(distinct=...)
  • has_permissions(...,group_id)
  • IS_MATCH(...,strict=True)
  • URL(...,scheme=,host=,port=), thanks Jonathan
  • admin in Afrikaans, thanks Caleb
  • auth.signature (experimental)
  • many other bug fixes


  • web2py comet via gluon/contrib/comet_messaging.py (html5 websockets) experimental
  • fixed problem with services (broken in 1.91.5), thanks Vollrath
  • customizable uploadwidget, thanks Fran
  • fixed problem with mail unicode support, thanks Richard
  • fixed problem with linkto=None and references fields in SQLTABLE, thanks villas
  • no more upgrade button on windows since does not work
  • better remember-me login, thanks Martin Weissenboeck
  • support for recatcha options
  • support for GAE namespaces via DAL('gae://namespace')
  • new rocket (1.2.2), thanks Tim
  • many other bug fixes and improvements (thanks Jonathan)


  • fixed a problem with deplyment on GAE
  • other new dal bug fixes


  • URL(...,hash_vars=...) allows to specify which vars need to be signed
  • fixed bug with aliasing in new DAL


  • fix issue with pickling new dal Row and Rows.


  • set poll = False in rocket because of poll python thread bug often unfixed, thanks Jonathan
  • fixes issue with crud and reCaptcha


  • pymysql no longer requires ssl (if not used)
  • fixed bug with virtualfields
  • fixed bug in truncate (new dal)
  • fixed bug in select with alternate primary key (new dal)
  • fixed bug with IS_IN_DB and self refences (also new dal)


  • new DAL (complete rewrite of the web2py DAL is more modular)
  • rewrite has fail safe reload, thanks Jonathan
  • better CAS with v2 support, thanks Olivier ROCH VILATO
  • better markmin2latex
  • session.connect(separate=True) to handle many session files, thanks huaiyu wang
  • changed bahvior of impersonate (more secure, can generate form or used as API)
  • new rocket, thanks Tim
  • new pyfpdf
  • no more old style classes
  • experimental couchdb support in new dal (only insert, select, update by id)
  • mysql support out of the box via pymysql
  • SQLITABLE(...,headers='labels') thanks Bruno
  • optional: digitally signed URLs, thanks Brian Meredyk
  • minor bug fixes


  • new admin layout (thanks Branko Vukelic)
  • new admin search
  • new admin language selector (thanks Yair)
  • new Welcome app (thanks Martin Mulone)
  • better wizard
  • admin support for DEMO_MODE=True
  • admin exposes GAE deployment button (always)
  • MENU support None links (thanks Michael Wolfe)
  • web2py.py -J for running cron (thanks Jonathan Lundell)
  • fixed ~db.table.id on GAE (thanks MicLee)
  • service.jsonrpc supports service.JsonRpcException (thanks Matt)
  • bug fixes


  • better list: string support, thanks Bob
  • jquery 1.4.3
  • scripts/autoroutes.py
  • new admin wizard
  • added retrieve_username to navbar (if username)
  • internal rewrite for arbitrary paths (abspath), thanks Jonathan
  • populate support for list: and decimal, thanks Chirstian
  • markmin2latex has extra attribute
  • better mercual admin allows list of files, versions and retrieve
  • new error report system, thanks Thadeus and Selecta
  • SQLFORM.accepts(detect_record_change).record_changed
  • fixed cron for bytecode compiled apps, thanks Álvaro J. Iradier Muro
  • other bugs fixes and pep8 compliant fixes


  • fixed a major bug introduced in 1.87.1 that prevents appadmin from working for new apps created with 1.87.1-2.
  • upgraded to clockpick 1.28, thanks villas


  • new layout for examples, thanks Bruno and Martin
  • admin allow DEMO_MODE=True and FILTER_APPS=['welcome']
  • fixed a possible problem with CRON and paths


  • Error reporting on save, thanks Mariano



  • markmin2latex
  • markmin2pdf
  • fixed some bugs
  • Storage getfirst, getlast, getall by Kevin and Nathan
  • db(db.table), db(db.table.id) both suported and equivalent to db(db.table.id>0)
  • postresql ssl support
  • less un-necessary logging and warnings on GAE
  • IS_DECIMAL_IN_RANGE and IS_FLOAT_IN_RANGE support dot="," (dot="." is default)
  • on_failed_authorization can be a function, thanks Niphold
  • gluon/contrib/login_methods/cas_auth.py for integration between CAS and Auth.


  • fixed some bugs
  • added pyfpdf, thank Mariano


  • flash now stays put in the top right corner
  • improved behavior for URL and T objects
  • new app level logging with logging.conf (thanks Jonathan)
  • improved OpenID (thanks Michele)
  • web2py_ajax handles prepend, append, hide (thanks Juris)
  • web2py_ajax also handels pre-validation of decimal fields
  • ru-ru translation (thanks Michele)
  • sk-sk translation (thanks Julius)
  • migrations save .table only if changed and after each ALTER TABLE (no more mysql inconsistencies)
  • fixed bugs in SQLCustomField, Field(default=...), IS_IMAGE, IS_DECIMAL_IN_RANGE and a few more.
  • Better validators (IS_DECIMAL_IN_RANGE, IS_INT_IN_RANGE, etc) thanks Jonatham
  • Polymmodel support on GAE
  • Experimental ListWidget
  • moved DAL and routes to thread.local (thanks Jonathan, again)
  • scripts/extract_mysql_models.py, thanks Falko Krause and Ron McOuat
  • scripts/dbsessions2trash.py, thanks Scott


  • mostly cleanup


  • New error reporting mechanism (thanks Mariano)
  • New routing system with app level routing (thanks Jonathan)
  • Integrated GAE appstat and GAE precompilation (thanks Scott)
  • New Field types "list:string", "list:integer", "list:reference"
  • request.cid, request.ajax, A(cid=request.cid), response.js


  • request.ajax to detect if action is called via ajax, tahnks Jonathan and David Mako
  • more captcha options, thanks Vidul
  • openid and oauth2 thanks Michele and Keith
  • better PluginManager and load components
  • new template system, thanks Thadeus
  • new db.table(id,[field=value]) and db.table(query) syntax
  • URL('index') (no more r=request), thanks Thadeus
  • mail.send(message='<html>...</html>', ....)
  • DAL([....]) for load balancing
  • @service.soap(...) with mysimplesoap, thanks Mariano
  • hideerror


  • Fixed a few bugs. The most important bugs we fixed are in memcache (thanks Scott) and in a process starvation issue with Rocket (thanks Mike Ellis and Tim).


  • Fixed gluon.tools to work work with load and base.css to nowrap labels


  • fixed bug in label names in formstyle
  • fixed id names in admin test.html page


  • fixed bug in Auth


  • rpx (janrain) support out of the box, allows login with Facebook, MySpace, etc. Thanks Mr Freeze
  • Increased security (escape single and double quotes, thanks Craig"
  • Fixed a bug with db.table.field.uploadseparate=True and autodelete
  • New welcome app with superfish and jQuery 1.4.2
  • Deleted openwysiwyg from admin
  • In XML and xmlescape quote defaults to True. Both ' and " are escaped. Thanks Craig Younkins


  • MARKMIN helper (no backward compatibility promise yet)
  • self._last_reference, thanks Dave (no backward compatibility promise yet)
  • zh-tw and better internationalization page, thanks Daniel Lin and Iceberg
  • better crud.search, thanks MrFreeze
  • Rocket interfaces, thanks Nik Klever
  • db.table.field.uploadseparate=True, thanks Gyuris
  • SCOPE_IDENITY for MSSQL, thanks Jose
  • fixed email attachment issue, thanks Bob_in_Comox
  • fixed problem with groupby and IS_IN_DB
  • other bug fixes
  • new implementation for local_import
  • ajax(..,...,null)
  • fixed Chrome bug in calendar.js, thanks Iceberg
  • experimental scrips/web2py-setup-fedora.sh
  • generic.load, thanks Iceberg


  • solved simplejson imcompatibility problem


  • x509 emails, thanks Gyuris
  • attachment and html in Mail on GAE, thanks PanosJee
  • fixed docstring in SQLTABLE, thanks aabelyakov
  • TAG(html) parese html into helpers (experimental, still some problems with unicode, , thanks RobertVa for unicode help)
  • DIV.elements(find=re.compile(....))
  • DIV.flatten()
  • DIV.elements('....') supports jQuery syntax in '....'
  • better it-it.py and it.py, thanks Marcello Della Longa
  • Many Bug fixes:
  • improved support for DAL and joins in postgresql/oracle, thanks Nico de Groot
  • bux fixex in html.py, thanks Ian
  • fixed an issue with registration_key==None, thanks Jay Kelkar
  • fixed bug in gql.py, thanks NoNoNo
  • fixed problem with multiple and checkboxes, thanks MIchael Howden
  • fixed bug in gae, thanks NoNoNo
  • restored 2.4 compatibility, thanks Paolo Gasparello
  • auth.update() when pictures in profile
  • formstyle can be a function, thanks Howden
  • escape in sanitizer, thanks Howes
  • add missing settings, thanks Hamdy
  • find and exclude return empty Rows instead of [], thanks iceberg
  • simplejson 2.1.1 should fix compatibility problems
  • added sms_utils and Authorize.net in contrib


  • reverted temporarily to old template system because of backward compatibility issues


  • new template system allows {{block name}}{{end}}, thanks Thadeus
  • fixed mime headers in emails, included PGP in emails, thanks Gyuris
  • automatic database retry connect when pooling and lost connections
  • OPTGROUP helper, thanks Iceberg
  • web2py_ajax_trap captures all form submissions, thank you Skiros
  • multicolumn checkwidget and arbitrary chars in multiple is_in_set, thanks hy
  • Québécois for welcome, thanks Chris
  • crud.search(), thanks Mr Freeze
  • DAL(...migrate,fake_migrate), thanks Thadeus


  • some cleanup of code in compileapp


  • fixed x-index in calendar


  • Replaced CherryPy with Rocket web server, thanks Tim
  • CacheOnDisk allows to specify a folder
  • IS_DATE/DATETIME can handle any year since 0
  • SQLTABLE(...,headers='fieldname:capitalize')
  • Field().with_alias, thanks Nathan and Mengu
  • has_membership(group=...,role=...), thank Jonathan
  • db.define_table(username=True), thanks Jonathan
  • gluon.tools.prettydate
  • can specify hostname in routes_out (same syntax as routes in), thanks Martin
  • db.table.bulk_insert([...records...]) now works on GAE, thanks Jon
  • IS_EMAIL validates on 'localhost', thanks Jonathan
  • welcome/views/layout.html uses ez.css, thanks Yarko
  • mail attachments support utf8, thanks szimszon
  • works with PyPy, thanks Joe
  • better Firebird support, thanks Jose
  • better Oracle support, thanks Gabriele
  • cron supports days of week
  • SQLFORM(...,formstyle="table3cols") or "table2cols" or "divs" or "ul"
  • crud.settings.formstyle
  • web2py.py -f folder allows to specify locations of applications, thanks Iceberg
  • better/faster regex in template works in Jython
  • fixed lots of small bugs


  • Fixed a typo in auth that created some registration problems


  • SQLTABLE(db(db.auth_user.id>0).select(),headers='fieldname:capitalize')
  • Oracle limitby improved (thanks Sergey)
  • fixed migrations in Firebird, thanks Jose Jachuf
  • gluon/contrib/login_methods/linkedin_account.py (to be tested)


  • major fix in cron (will I ever get this 100% right?)
  • fix in delete for GAE
  • auth.settings.login_captcha and auth.settings.register_captcha
  • crud.settings.create_captcha and crud.settings.update_captcha
  • automatic update button in admin


  • editarea 0.8.2 + zencoding
  • new (better) cron locking meachnism
  • no storing session cookies on session.forget(), thank you Alvaro
  • routes_apps_raw allows disabling of request.args validation, thanks Jonathan and Denes
  • fixed problem with edit_languages ad multiple tabs, thanks Iceberg
  • crud captcha, thanks you Nathan
  • softcron disabled by default in wsgihandler and fcgihandler


  • fixed behaviour with languages.py, thanks Iceberg
  • added chinese (thanks Iceberg) and Hungarian (thanks Gyuris)
  • fixed problem with GAE deleted by id (thanks what_ho)
  • fixed bug in LOAD with custom views, thanks vhang
  • improved IS_IN_SET takes iterator, dict, list and list of tuples, thanks Iceberg
  • Auth(...,controller='default')
  • Fixed major bug in parsing repeated request.vars, thanks Ben
  • IS_DATE and IS_DATETIME can now handle any 0<year
  • allow to disable editarea onload, thanks Alex


  • customizable BEAUTIFY, thanks John


  • added support for PAM authentican for apps and for admin


  • fetch supports cache
  • curd.update(....,onaccept=crud.archive) magic
  • new UUID mechnism fixes session conflicts with cloned machine in cloud
  • allow to upload app and overwrite existing old ones, thanks Jonathan
  • print gluon.tools.prettydate(request.now,T), thanks Richard


  • better cron
  • better fetch
  • logging of email failures
  • new web2py.fedora.sh
  • new setup-web2py-ubuntu.sh
  • experimental autocomplete
  • menus work on IE6


  • IS_IN_SET(((0,'label0'),(1,'label1'))), thanks Falko Krause
  • SQLFORM(...).accpets stores True or False in boolean types no None, thanks Frederik Wagner
  • SQLFORM.factory(...,table_name='no_table'), thanks Thedeus
  • jQuery 1.4.1
  • Fixed major problem with internationalization of multiple languages.
  • Fixed a serius security issue with login
  • Possibly fixed some issues with cron


  • IS_SLUG, thanks Gustavo and Jonathan
  • web2py.py -nogui, thanks Jeff Bauer
  • solved a problem with jython, thanks Tim Farrel
  • login has "remember be option", thanks Piotr Banasziewicz
  • fixed problem with keepvalue in update forms, thanks Miguel Lopez


  • request_password_reset and password reset verification
  • python web2py.py -S app -M -R script.py -A arg1 arg2 arg3
  • T("%(a)s") % dict(a="hello")


  • bug fixes
  • IS_IN_DB(...,_and=IS_NOT_IN_DB)
  • Smaller populate, thanks Piotr
  • better slicing of fields, thanks Michael Fig
  • Cache stats, thanks Thadeus
  • Better gql.py
  • IS_IN_DB and IS_IN_SET default to zero='', no longer zero=None


  • bug fixes
  • restored python 2.4 support,thanks ont.rif
  • support for native types on Google App Engine
  • cache.ram usage statictics, thanks Thadus
  • no more auth manu in scaffolding
  • no more spash screen with -Q
  • fixed doctest in html.py, thanks Anand Vaidya
  • export_to_csv_file has represent, thanks Thadeus


  • Fix bugs including including unicode in emails and blobs on GAE


  • Moved to mercurial
  • Default validators use the new define_table(....,format='...')
  • New get_vars and post_vars compatible in 2.5 and 2.6 (thanks Tim)
  • Major rewrite of gql.py extends DAL syntax on GAE
  • No more *.w2p, welcome.w2p is create automatically, base apps are always upgraded
  • export_to_csv(delimiter = ',', quotechar = '"', quoting = csv.QUOTE_MINIMAL), thanks Thadeus


  • Fixed problem with storage and comparison of Row objects
  • Fixed problem with mail on GAE
  • Fixed problem with T in IS_DATE(TIME) error_message and format
  • Rows[i].delete_record()
  • Even better support for legacy databases
  • Experimantal support for non UTF8 encoding in DB
  • Better IPV4 (thanks Thandeus)
  • T.current_languages default to 'en' and new T.set_current_languages(...) (thanks Yarko)
  • INPUT(...,hideerror=False) used to fix rare chechbox widget problem
  • Admin allows change of admin password
  • New gluon/contrib/populate.py
  • Size of input/textarea set by CSS no more by jQuery (thanks Iceberg)
  • Customizable CSV (thanks Thandeus)
  • More bug fixed (thanks Thandeus)
  • Better regex for template fixed Jython problem (thank Jonathan)

1.72.1 - 1.72.3

  • Better support for legacy databases


  • Complete rewrite of Rows
  • renamed DALStorage->Rows, DALRef->Reference
  • Experimental serializarion of Row and Rows (get serialized to dict and list of dict)
  • DAL(...,folder) and template.render(content=, context=) make it more modular


  • Fixed bug with Rows.as_list and DALRef
  • Added Rows.as_dict (thanks Mr Freeze and Thedeus)
  • Added request.wsgi (thanks hcvst) allows running wsgi apps under web2py and applying wegi middleware to regular web2py actions that return strings.
  • Experimental distributed transactions between postgresql, mysql and firebird
  • Finally local_import is here!


  • Fixed a bug introduced in 1.68 about inserting unicode in DAL
  • Fixed other small bugs
  • Better support for legacy databases (thank Denes)
  • response.meta replaces response.author, response.keywords, response.description
  • response.files stets dependes in plugins
  • better admin for packing/unpacking plugins
  • reference fiels nor evaluate to DALRef with lazy evaluation (cool, thanks Mr Freeze)
  • can insert a record in place of a reference
  • record[e] instead of record._extra[e] (tentatively!)
  • record.update_record() with no args
  • rows.find() (thanks Mr Freeze)
  • rows.exclude()
  • rows.sort()
  • rows[:]


  • Fixing bug with admin and missing crontab
  • Fixing bug with rewrite.load on GAE (thanks Willian Wang)


  • New official markdown with security fix
  • rows.first()
  • rows.last()
  • New cron
  • New hindi and spanish translation
  • cached uploads allow for progress bars (thanks AndCycle)
  • ingres support (thanks Chris)
  • legacy database support for db2, mssql with non-int primary keys (thanks Denes)
  • default setting of content-type (this may cause strange behavior in old apps when downloading images)
  • IS_UPPER and IS_LOWER works with unicode
  • CLENUP not takes regex of allowed/now allowed chartares
  • New rewrite.py allows dynamic routes
  • Better error messages for IS_INT_* and IS_FLOAT_*


  • Security fix in markdown


  • Bux fixed


  • Python 2.4 support (again)
  • New layout for welcome
  • changed defauld field sizes to 512
  • Field(uploadfolder="...")
  • appadmin works on GAE (again, somehting got broken at some point)
  • new wsgiserver 3.2.0 should fix recurrent broken download problems


  • new doctypes
  • form.vars.newfilename
  • new HTML and XHTML helpers
  • better IS_LENGTH


  • request.url (thanks Jonathan)
  • restored uploadfield_newfilename
  • new examples layout nad logo (thanks Mateusz)


  • lables in auth auto-translate (thanks Alvaro)
  • better ldap_auth (thanks Fran)
  • auth chacks locally for blocked accounts even for alternate login methods (thanks Fran)


  • Fixed a sqlhtml bug with image upload


  • Fixed some small bugs and typos in the docstrings
  • Fixed AMF3 support


  • Fixed some small auth bugs
  • Field.store(...)


  • spreadsheet
  • shell history, thanks sherdim
  • crontab editor, thanks Angelo
  • gluon/contrib/login_methods/cas_auth.py (thanks Hans)
  • DAL(...) instead of SQLDB(...)
  • DAL('gae') instead of GQLDB()
  • Field instead of SQLField
  • (the old syntax still works)


  • reST docstrings for Sphinx, thanks Hans
  • gluon/conrtib/login_methods/gae_google_account.py for google CAS login on GAE, thanks Hans
  • fixed problem with Auth and Firebird 'password' issue
  • new auth.settings.create_user_groups
  • tickets stored on datastore on GAE and also logged, thanks Hans
  • imporved IS_LENGTH with max and min, thanks Mateusz
  • improved IS_EMAIL with filters, thanks Mateusz
  • new IS_IMAGE checks for format and size, thanks Mateusz
  • new IS_IPV4, thanks Mateusz


  • Som bug fixes
  • Informix Support
  • response.render(stream)
  • SQLFORM.factory
  • SQLFORM.widgets.radio and SQLFORM.widgets.checkboxes


  • Some bug fixes


  • New IS_COMPLEX validator, thank Mr. Freeze
  • Experimental Informix support
  • Autologin on registration


  • Models 2-3 times faster (thanks Alexey)
  • Better LDAP support
  • Works with Jython (including sqlite and postgresql with zxJDBC):
  • download jython-2.5rc3.jar
  • download qlite-jdbc-
  • java -jar jython-xxx.jar
  • export CLASSPATH=$CLASSPATH:/Users/mdipierro/jython2.5rc3/sqlite-jdbc-
  • cd web2py
  • ../jython2.5rc3/jython web2py.py


  • You can do jQuery.noConflict() without breaking web2py_ajax
  • Wigets can have attributes (thanks Hans)
  • Lots of internal cleanup and better code reusage (thanks Hans)


  • no more import gluon.
  • support for generic.xxx
  • simplejson can handle datetime date and time


  • SQLFORMS and crud now show readble fields
  • Better WingIDE support
  • Languages are automatically translated
  • T.force and lazyT works better, optional T.lazy=False
  • gluon.storage.Messages are now translated without T
  • if routes.py then request.env.web2py_original_uri
  • db.table.field.isattachment = True
  • internationalizaiton of admin by Yair
  • admin.py by Alvaro
  • new MENU helper
  • new w2p file format
  • new welcome app with auth, service and crud turned on


  • fixed some typos
  • auth.add_permissions(0,....) 0 indicates group of current user
  • crud.update has deletable=True or False
  • fixed issue with GAE detection -> gluon.settings.web2py_runtime -> request


  • fixed lots of small bugs
  • routes_in can filter by http_host


  • Fixed some CRON bugs
  • Fixed a bug with new ajax edit
  • Experimental DB2 support in DAL
  • Customizable font size in admin edit page
  • New welcome/models/db.py shows how to memcache sessions on GAE with MEMDB
  • More expressive titles in admin
  • DB2 support. Thanks Denes!


  • New ajax edit with keepalive (no longer logged out when editing code)
  • Fixed conflict resolution page.
  • Removed /user/bin/python from models/controllers


  • fixing lots of small bugs with tool and languages
  • jquery.1.3.2

  • One more feature in trunk....
  • db.define_table('image',SQLField('file','upload'))
  • db.image.file.authorize=lambda row: True or False
  • then controller
  • def download(): return response.download(request,db)
  • id' is now a hidden field sqlform
  • gql references converted to long
  • admin login has autofocus
  • new notation proposed by Robin, db.table[id]
  • new UploadWidget shows images
  • new generic.html shows request, response, session
  • new LEGEND helper (thanks Marcus)
  • fixed doctests in sql (thanks Robin)
  • new notation for DB
  • record=db.table[id]
  • db.table[id]=dict(...)
  • del db.table[id]
  • request.env.web2py_version
  • new class gluon.storage.Settings has lock_keys, lock_values
  • jquery 1.3.1
  • PEP8 compliance
  • new examples application
  • runs on jython (no database drivers yet, thanks Phyo)
  • fixed bugs in tests
  • passes all unittest but test_rewite (not sure it should pass that one)
  • Lots of patches from Fran Boone (about tools) and Dougla Soares de Andarde (Python 2.6 compliance, user use of hashlib instead of md5, new markdown2.py)
  • db.define_table('mytable',db.Field('somefield'),timestamp)



and use it in all your tables

  • form=SQLFORM(db.circle,request.args[-1])
  • and you get a create form if the URL ends in /0, you get an update
  • form if the URL ends in /[valid_record_id]

make a display form in two possible ways:

  • form=SQLFORM(db.circle,record,readonly=True)
  • form=SQLFORM(db.circle,record_id,readonly=True)

make an update form in two possible ways:

  • form=SQLFORM(db.circle,record)
  • form=SQLFORM(db.circle,record_id)

make a create form in two possible ways:

  • form=SQLFORM(db.circle)
  • form=SQLFORM(db.circle,0)

make a form that automatically computes area

  • pi=3.1415
  • form=SQLFOM(db.circle)
  • if form.accepts(request.vars,
  • onvalidation=lambda form: form.vars.area=pi*form.vars.radius2): ...

make the radius appear in bold in display and table

  • db.circle.radius.represent=lambda value: B(value)

automatically timestamp when record is modified

  • db.circle.modified_on.update=request.now

automatically timestamp when record cretaed

  • db.circle.modified_on.default=request.now

do not show now in display forms

  • db.circle.modified_on.readable=False

do not show area in create/edit forms

  • db.circle.area.writable=False

add a comment in the forms

  • db.circle.area.comment="(this is a comment)"


  • Now you can do:


  • rowcount
  • fixed bug when IS_IN_DB involved multiple fields on GAE
  • T.set_current_languages
  • better unittests
  • response.custom_commit and response.custom_rollback
  • you can next cache calls (like cache a controller that caches a select). Thanks Iceberg
  • db(....id==None).select() no longer returns an error but an empty SQLRows on GAE
  • db(...).delete(delete_uploads=True) and SQLFORM.accepts(....delete_uploads=True) will delete all referenced uploaded files
  • DIV.element and DIV.update
  • sqlrows.json()
  • SQLFORM.widgets
  • URL(r=request,args=0)
  • IS_IN_DB(...,multiple=True) for Many2Many (sort of)
  • In URL(...,f) f is url encoded
  • In routes_in=
  • simplejson 2.0.7


  • fixed minor bugs


  • On GAE upload data goes automatically in datastore (blob created automatically)
  • New appadmin runs on GAE (most of it, not all)
  • Martin Hufsky patch allow slicing of fields in DAL expressions


  • Fixed a minor bug with _extra[key] and key not str.
  • check for upgrade via ajax


  • Fixed more bugs introduced in 1.49 (sql _extra and html select)
  • support for sqlite:memory:


  • Fixed some bugs introduced in 1.49


  • fixed a bug with taskbar widget, thanks Mark
  • fixed a bug with form.latest
  • made many DIV methods private (_)


  • html.py rewrite (better support for custom forms) (Bill Ferrett)
  • new stickers in examples (thanks Mateusz)
  • on windows can run in taskbar (Mark Larsen)
  • in admin|edit page link to edit|controller (Nathan Freeze)
  • better error codes and routes_onerror (Timothy Farrell)
  • DAL support for groupy and having
  • DAL support for expressions instead of values
  • DAL has experimental Informix support
  • fixed bug with non-printable chars in DAL
  • 'text' fields limited to 216 (to avoid mysql problems)
  • widget has -quiet and -debug (Attila Csipa)
  • web2py_session uses BLOB instead of TEXT
  • improved IS_URL
  • Runs with python 2.6 (Tim)
  • On GAE uses GAE for static files (Robin)


  • fixed security issue by removing slash escape in mysql
  • removed random everywhere
  • use uuid for session and tickets
  • use http_x_forward_for to figure out the client causing a ticket
  • use longtext and longblob for mysql
  • main now really catches all exceptions
  • no more warnings on GAE

web2py 1.31-1.41

  • some bug fixes, mostly better appengine support
  • mssql support
  • firebird support
  • widgets support
  • connection pools

web2py 1.30

  • added flv to contenttype
  • added support for appengine

web2py 1.29

  • Now selet mutliple works with get, so does is IS_LENGTH
  • Added IS_LIST_OF
  • fixed problem with admin from windows and localhost

web2py 1.28

  • fixed bug with belongs, faster sql.py
  • included jquery.js
  • minor aestetical fixes
  • sortable.js is gone

web2py 1.27

  • IS_NULL_OR now works will all fields
  • admin creates paths to static files
  • wsgiserver options are passed to HttpServer
  • faking limitby for oracle to make appadmin work
  • all objects inherit from object
  • fixed bug in app names with .
  • fixed bug in created RestrictedError object on windows
  • shell is now in gluon and accessible via web2py.py

web2py 1.26

  • added shell.py (thanks Limodou!)
  • added memcache support

web2py 1.22-1.25

  • fixed minor bugs, added IS_NULL_OR

web2py 1.21

  • replaced paste.httpserver with cherrypy.wsgi server
  • temporary sessions are no longer saved
  • widget has [stop] button and graph
  • logging is done by main by appfactory
  • fixed a bug in sql belongs

web2py 1.20

  • new IFRAME, LABEL, FIELDSET validators
  • P(..cr2br=True) option
  • FORM and SQLFORM have hidden=dict(...) option for REST
  • testing framework.
  • improved examples pages

web2py 1.19

  • minor typos

web2py v1.18

  • removed vulnerability in accept_languages and session_id
  • Minor bug fixes. Typos and cleanup cache. Textarea now clears.
  • Support for PyAMF.
  • T returns a class, not a string
  • new template parser (faster?)
  • got rid of sintaxhighlighter in favor of server side CODE
  • fix problem with cacheondisk locking
  • fix 'None' instead of NULL in IS_NOT_IN_DB (I think)
  • gluon.contrib.markdown
  • notnull and unique in SQLField now supported (tested on sqlite mysql and postgresql)
  • Storage now has __getstate__ and __setstate__ needed for pickling.
  • session files are now locked to make it work better with asynchronous requests
  • cxoracle should work, apart for limitby
  • .../examples is now mapped to .../examples/default/index etc.
  • .../init is now mapped to .../welcome if init is not present

web2py v1.17

  • I posted v1.16 too soon. v1.17 was released after 1h to fix some bugs.

web2py v1.16

  • yes we changed the name! Turns out Gluon was trademarked by somebody else.
  • Although we are not infringing the trademark since this is a non-commercial
  • product we could have run into some issues. So we have been professional
  • and changed the name to web2py.
  • Now SQLFORMs and FORM can have a formname and multiple forms are allowed
  • per page.
  • A new examples/default/index page.
  • web2py.py instead of runme.py
  • mysql sets utf8 encoding.
  • input integer field values are automatically converted int().

Gluon v1.15

  • New try:... except. in gluon/main.py for when sessions cannot be saved
  • Now validator/formatter method allows IS_DATE('%d/%m/%Y')

Gluon v1.14

  • Fixed a bug fix in URLs

Gluon v1.13

  • (this is one of the biggest revisions ever)
  • Improved sql.py has support MySQL, cxOracle (experimental), extract, like and better testing
  • SQLDB.tables and SQLTable.fields are now SQLCalableList objects
  • Fixed bug with editing integer fields storing zero
  • Admin interface now says "insert new [tablename]" and display insert, select or update properly in the title.
  • Added a cache mechamism. Works for data, controllers, views and SQLRows.
  • main.py now uses a request.folder absolute path when not os.name in ['nt','posix']. Seems to work on windowsce devices, except no file locking has consequences.
  • Now you can put modules in applications/[anyapp]/modules and import them with
  • import applications.[anyapp].modules.[module] as [module]
  • Fixed problem with init
  • New applications/examples/controller/global.py controller for docs.

Gluon v1.12

  • in sql.py
  • handles NULL values properly
  • unicode support (data always stored in utf-8)
  • 'date' -> datetime.date ,'time' -> datetime.time, 'datetime' -> datetime.datetime, 'boolean' -> True/False
  • most types have default validators
  • SQLField(...,required=True) option.
  • SQLRows has __str__ that serializes in CSV and xml() that serializes in HTML
  • SQLTable has import_from_csv_file(...)
  • gluon.simplejson for AJAX
  • in validators.py
  • IS_IN_DB(db,..) - db can be an SQLSet or an SQLDB
  • better error messages
  • in admin
  • new import/export in csv, update and delete interface.
  • in appadmin
  • edit form allows to keep stored encrypted password
  • in main.py
  • http://host not defaults to http://host/init/default/index
  • New third party modules
  • gluon.simplejson(.dumps, .loads)
  • gluon.pyrtf(.dumps)
  • gluon.rss2(.dumps)

Gluon v1.11

  • appadmin allows to keep or delete uploaded files

Gluon v1.10

  • fixed concurrency problems with SQLDB._instances and SQLDB._folders, now use lock
  • now, by default, edit SQLFORMs retain uploaded files

Gluon v1.9

  • allow "count(*)" in select
  • db.execute()
  • fixed problem with continue and return in template
  • removed try: ... except in sql.py
  • fixed '\t'

Gluon v1.8

  • no more chdir (thread unsafe)
  • no more sys.stdout (thread unsafe)
  • response.body is StringIO()
  • admin/default/site informs about upgrade
  • response.locker (optional)

Gluon v1.5

  • <form> -> <form method="post"> in errors.html
  • replace('//','////') in sub in template.py

Gluon v1.4

  • fixed problem with IS_INT_IN_RANGE and IS_FLOAT_IN_RANGE. Now an error in a validator is reported as a ticket. Good validators should not raise Exceptions.
  • IS_IN_DB displays "label (id)"
  • it can upload files without extension
  • migration is now optional (define_table has migrate=False option)

Gluon v1.3

  • added IS_IN_DB, IS_NOT_IN_DB and updated examples accordingly

Gluon v1.1 -> v1.2

  • fixed some typos in examples
  • IS_IN_SET now supports labels
  • cleanup in sql.py does not cleanup, just checks valid field and table names

Gluon v1.0 -> v1.1

  • bug in sqlhtml with JOINS queries

EWF v1.7 -> Gluon v1.0

  • Name change
  • Improved layout.html

EWF v1.6 -> v1.7

  • in paths replace '' with '/' to fix problem with windows paths
  • using limitby in database administration
  • replaced mime/miltupart with multipart/form-data to fix a windows problem

EWF v1.5 -> v1.6 (2007)

  • load and save .py in ascii, avoids problem with LF+CR on windows
  • added path.join in compileapp, fixed problem with Windows compileapp