diff --git a/VERSION b/VERSION index b7e8be4c..4ad8a736 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 1.99.3 (2011-11-23 15:05:14) dev +Version 1.99.3 (2011-11-23 16:35:01) dev diff --git a/applications/examples/controllers/ajax_examples.py b/applications/examples/controllers/ajax_examples.py index b39013b6..8351a4e6 100644 --- a/applications/examples/controllers/ajax_examples.py +++ b/applications/examples/controllers/ajax_examples.py @@ -1,7 +1,3 @@ - - - - def index(): return dict() diff --git a/applications/examples/controllers/database_examples.py b/applications/examples/controllers/database_examples.py index 9d9cccf9..a98421b8 100644 --- a/applications/examples/controllers/database_examples.py +++ b/applications/examples/controllers/database_examples.py @@ -1,51 +1,50 @@ from gluon.fileutils import read_file -response.menu = [['Register User', False, URL(r=request, - f='register_user')], ['Register Dog', False, - URL('register_dog')], ['Register Product' - , False, URL('register_product')], +response.menu = [['Register Person', False, URL('register_person')], + ['Register Dog', False, URL('register_dog')], + ['Register Product', False, URL('register_product')], ['Buy product', False, URL('buy')]] -def register_user(): - """ simple user registration form with validation and database.insert() +def register_person(): + """ simple person registration form with validation and database.insert() also lists all records currently in the table""" - # ## create an insert form from the table + # create an insert form from the table + form = SQLFORM(db.person) - form = SQLFORM(db.users) - - # ## if form correct perform the insert - - if form.accepts(request.vars, session): + # if form correct perform the insert + if form.process().accepted: response.flash = 'new record inserted' - # ## and get a list of all users + # and get a list of all persons + records = SQLTABLE(db().select(db.person.ALL),headers='fieldname:capitalize') - records = SQLTABLE(db().select(db.users.ALL)) return dict(form=form, records=records) def register_dog(): - """ simple user registration form with validation and database.insert() + """ simple person registration form with validation and database.insert() also lists all records currently in the table""" - form = SQLFORM(db.dogs) - if form.accepts(request.vars, session): + form = SQLFORM(db.dog) + if form.process().accepted: response.flash = 'new record inserted' download = URL('download') # to see the picture - records = SQLTABLE(db().select(db.dogs.ALL), upload=download) + records = SQLTABLE(db().select(db.dog.ALL), upload=download, + headers='fieldname:capitalize') return dict(form=form, records=records) def register_product(): - """ simple user registration form with validation and database.insert() + """ simple person registration form with validation and database.insert() also lists all records currently in the table""" - form = SQLFORM(db.products) - if form.accepts(request.vars, session): + form = SQLFORM(db.product) + if form.process().accepted: response.flash = 'new record inserted' - records = SQLTABLE(db().select(db.products.ALL)) + records = SQLTABLE(db().select(db.product.ALL), + headers='fieldname:capitalize') return dict(form=form, records=records) @@ -53,100 +52,38 @@ def buy(): """ uses a form to query who is buying what. validates form and updates existing record or inserts new record in purchases """ - buyerRecords = db().select(db.users.ALL) - buyerOptions = [] - for row in buyerRecords: - buyerOptions.append(OPTION(row.name, _value=row.id)) + form = SQLFORM.factory( + Field('buyer_id',requires=IS_IN_DB(db,db.person.id,'%(name)s')), + Field('product_id',requires=IS_IN_DB(db,db.product.id,'%(name)s')), + Field('quantity','integer',requires=IS_INT_IN_RANGE(1,100))) + if form.process().accepted: + # get previous purchese + purchase = db((db.purchase.buyer_id == form.vars.buyer_id)& + (db.purchase.product_id==form.vars.product_id)).select().first() - productRecords = db().select(db.products.ALL) - productOptions = [] - for row in productRecords: - productOptions.append(OPTION(row.name, _value=row.id)) - - form = FORM(TABLE( - TR('Buyer id:', - SELECT(buyerOptions,_name='buyer_id')), - TR('Product id:', - SELECT(productOptions,_name='product_id')), - TR('Quantity:', - INPUT(_type='text', _name='quantity', - requires=IS_INT_IN_RANGE(1, 100))), - TR('', - INPUT(_type='submit', _value='Order')) - )) - if form.accepts(request.vars, session, keepvalues=True): - - # ## check if user is in the database - - if len(db(db.users.id == form.vars.buyer_id).select()) == 0: - form.errors.buyer_id = 'buyer not in database' - - # ## check if product is the database - - if len(db(db.products.id == form.vars.product_id).select())\ - == 0: - form.errors.product_id = 'product not in database' - - # ## if no errors - - if len(form.errors) == 0: - - # ## get a list of same purchases by same user - - purchases = db((db.purchases.buyer_id == form.vars.buyer_id) - & (db.purchases.product_id - == form.vars.product_id)).select() - - # ## if list contains a record, update that record - - if len(purchases) > 0: - purchases[0].update_record(quantity=purchases[0].quantity - + form.vars.quantity) - else: - - # ## or insert a new record in table - db.purchases.insert(buyer_id=form.vars.buyer_id, - product_id=form.vars.product_id, - quantity=form.vars.quantity) - response.flash = 'product purchased!' - if len(form.errors): + if purchase: + # if list contains a record, update that record + purchase.update_record( + quantity = purchase.quantity+form.vars.quantity) + else: + # self insert a new record in table + db.purchase.insert(buyer_id=form.vars.buyer_id, + product_id=form.vars.product_id, + quantity=form.vars.quantity) + response.flash = 'product purchased!' + elif form.errors: response.flash = 'invalid values in form!' - # ## now get a list of all purchases - - # quick fix to make it runnable on gae - if purchased: - records = db(purchased).select(db.users.name, - db.purchases.quantity, - db.products.name) - else: - records = db().select(db.purchases.ALL) - return dict(form=form, records=SQLTABLE(records), vars=form.vars, - vars2=request.vars) + # now get a list of all purchases + records = SQLTABLE(db(purchased).select(),headers='fieldname:capitalize') + return dict(form=form, records=records) def delete_purchased(): """ delete all records in purchases """ - - db(db.purchases.id > 0).delete() + db(db.purchase.id > 0).delete() redirect(URL('buy')) - -def reset_purchased(): - """ set quantity=0 for all records in purchases """ - - db(db.purchases.id > 0).update(quantity=0) - redirect(URL('buy')) - - def download(): """ used to download uploaded files """ - - import gluon.contenttype - app = request.application - filename = request.args[0] - response.headers['Content-Type'] = \ - gluon.contenttype.contenttype(filename) - return read_file('applications/%s/uploads/%s' % (app, filename), 'rb') - - + return response.download(request,db) diff --git a/applications/examples/controllers/default.py b/applications/examples/controllers/default.py index 2a1770fd..e8a076d2 100644 --- a/applications/examples/controllers/default.py +++ b/applications/examples/controllers/default.py @@ -8,11 +8,11 @@ response.description = T('web2py Web Framework') session.forget() -@cache('index') +#@cache('index') def index(): return response.render() -@cache('what') +#@cache('what') def what(): import urllib; try: @@ -21,30 +21,30 @@ def what(): images = [] return response.render(images=images) -@cache('download') +#@cache('download') def download(): return response.render() -@cache('who') +#@cache('who') def who(): return response.render() -@cache('support') +#@cache('support') def support(): return response.render() -@cache('documentation') +#@cache('documentation') def documentation(): return response.render() -@cache('usergroups') +#@cache('usergroups') def usergroups(): return response.render() def contact(): redirect(URL('default','usergroups')) -@cache('videos') +#@cache('videos') def videos(): return response.render() @@ -54,7 +54,7 @@ def security(): def api(): redirect('http://web2py.com/book/default/chapter/04#API') -@cache('license') +#@cache('license') def license(): import os filename = os.path.join(request.env.gluon_parent, 'LICENSE') @@ -63,11 +63,11 @@ def license(): def version(): return 'Version %s.%s.%s (%s) %s' % request.env.web2py_version -@cache('examples') +#@cache('examples') def examples(): return response.render() -@cache('changelog') +#@cache('changelog') def changelog(): import os filename = os.path.join(request.env.gluon_parent, 'CHANGELOG') diff --git a/applications/examples/controllers/layout_examples.py b/applications/examples/controllers/layout_examples.py index 40f5b6f3..c7360878 100644 --- a/applications/examples/controllers/layout_examples.py +++ b/applications/examples/controllers/layout_examples.py @@ -1,6 +1,3 @@ - - - def civilized(): response.menu = [['civilized', True, URL('civilized' )], ['slick', False, URL('slick')], diff --git a/applications/examples/controllers/simple_examples.py b/applications/examples/controllers/simple_examples.py index bbd7c053..cf25d73f 100644 --- a/applications/examples/controllers/simple_examples.py +++ b/applications/examples/controllers/simple_examples.py @@ -39,7 +39,7 @@ def hello6(): def status(): """ page that shows internal status""" response.view = 'generic.html' - return dict(request=request, session=session, response=response) + return dict(toolbar=response.toolbar()) def redirectme(): diff --git a/applications/examples/models/database_examples/db.py b/applications/examples/models/database_examples/db.py index 1a1025c1..417805b5 100644 --- a/applications/examples/models/database_examples/db.py +++ b/applications/examples/models/database_examples/db.py @@ -18,52 +18,55 @@ else: db = DAL('sqlite://storage.sqlite') db.define_table( - 'users', + 'person', Field('name'), - Field('email') + Field('email'), + format = '%(name)s', + singular = 'Person', + plural = 'Persons', ) -# ONE (users) TO MANY (dogs) +# ONE (person) TO MANY (dogs) db.define_table( - 'dogs', - Field('owner_id', db.users), + 'dog', + Field('owner_id', db.person), Field('name'), Field('type'), Field('vaccinated', 'boolean', default=False), Field('picture', 'upload', default=''), + format = '%(name)s', + singular = 'Dog', + plural = 'Dogs', ) db.define_table( - 'products', + 'product', Field('name'), - Field('description', 'text') + Field('description', 'text'), + format = '%(name)s', + singular = 'Product', + plural = 'Products', ) -# MANY (users) TO MANY (purchases) +# MANY (persons) TO MANY (purchases) db.define_table( - 'purchases', - Field('buyer_id', db.users), - Field('product_id', db.products), - Field('quantity', 'integer') + 'purchase', + Field('buyer_id', db.person), + Field('product_id', db.product), + Field('quantity', 'integer'), + format = '%(quantity)s %(product_id)s -> %(buyer_id)s', + singular = 'Purchase', + plural = 'Purchases', ) -# if running on Google App Engine -if settings.web2py_runtime_gae: - # quick hack to skip the join - purchased = None -else: - # use a joined view - purchased = (db.users.id == db.purchases.buyer_id) & (db.products.id - == db.purchases.product_id) +purchased = \ + (db.person.id==db.purchase.buyer_id)&\ + (db.product.id==db.purchase.product_id) -db.users.name.requires = IS_NOT_EMPTY() -db.users.email.requires = [IS_EMAIL(), IS_NOT_IN_DB(db, 'users.email')] -db.dogs.owner_id.requires = IS_IN_DB(db, 'users.id', 'users.name') -db.dogs.name.requires = IS_NOT_EMPTY() -db.dogs.type.requires = IS_IN_SET(['small', 'medium', 'large']) -db.purchases.buyer_id.requires = IS_IN_DB(db, 'users.id', 'users.name') -db.purchases.product_id.requires = IS_IN_DB(db, 'products.id', - 'products.name') -db.purchases.quantity.requires = IS_INT_IN_RANGE(0, 10) +db.person.name.requires = IS_NOT_EMPTY() +db.person.email.requires = [IS_EMAIL(), IS_NOT_IN_DB(db, 'person.email')] +db.dog.name.requires = IS_NOT_EMPTY() +db.dog.type.requires = IS_IN_SET(('small', 'medium', 'large')) +db.purchase.quantity.requires = IS_INT_IN_RANGE(0, 10) diff --git a/applications/examples/static/css/examples.css b/applications/examples/static/css/examples.css index ade32c64..b262c124 100644 --- a/applications/examples/static/css/examples.css +++ b/applications/examples/static/css/examples.css @@ -19,4 +19,4 @@ input:focus,textarea:focus {background:#f0f0f0!important} table.downloads { width:100%; } table.downloads th, table.downloads td {text-align:center;} table.downloads a.button { width: 150px; } - +th,td {padding-right: 10px;} \ No newline at end of file diff --git a/applications/examples/static/css/web2py.css b/applications/examples/static/css/web2py.css index 4833b5d7..2d1b7734 100644 --- a/applications/examples/static/css/web2py.css +++ b/applications/examples/static/css/web2py.css @@ -77,7 +77,7 @@ fieldset { padding: 16px; border-top: 1px #DEDEDE solid;} fieldset legend {text-transform:uppercase; font-weight: bold; padding: 4px 16px 4px 16px; background: #f1f1f1;} /* fix ie problem with menu */ -.ie-lte7 .topbar {z-index: 2; } +.ie-lte7 .topbar .container {z-index: 2; } td.w2p_fw {padding-bottom: 1em;} td.w2p_fl, td.w2p_fw, td.w2p_fc { vertical-align:top; } diff --git a/applications/examples/views/database_examples/buy.html b/applications/examples/views/database_examples/buy.html index e74b856a..d69a861e 100644 --- a/applications/examples/views/database_examples/buy.html +++ b/applications/examples/views/database_examples/buy.html @@ -1,7 +1,6 @@ -{{extend 'layout_examples/layout_civilized.html'}} -

Purchase form

+{{extend 'layout.html'}} +

Purchase form

{{=form}} - [ {{=A('reset purchased',_href=URL('reset_purchased'))}} | - {{=A('delete purchased',_href=URL('delete_purchased'))}} ]
+ [ {{=A('delete purchases',_href=URL('delete_purchased'))}} ]

Current purchases (SQL JOIN!)

-

{{=records}}

\ No newline at end of file +

{{=records}}

diff --git a/applications/examples/views/database_examples/register_dog.html b/applications/examples/views/database_examples/register_dog.html index 59f799e8..440e4c04 100644 --- a/applications/examples/views/database_examples/register_dog.html +++ b/applications/examples/views/database_examples/register_dog.html @@ -1,6 +1,6 @@ -{{extend 'layout_examples/layout_civilized.html'}} +{{extend 'layout.html'}}

Dog registration form

{{=form}}

Current dogs

-{{=records}} \ No newline at end of file +{{=records}} diff --git a/applications/examples/views/database_examples/register_user.html b/applications/examples/views/database_examples/register_person.html similarity index 51% rename from applications/examples/views/database_examples/register_user.html rename to applications/examples/views/database_examples/register_person.html index c2b0e562..53030d1b 100644 --- a/applications/examples/views/database_examples/register_user.html +++ b/applications/examples/views/database_examples/register_person.html @@ -1,6 +1,6 @@ -{{extend 'layout_examples/layout_civilized.html'}} +{{extend 'layout.html'}}

User registration form

{{=form}}

Current users

-{{=records}} \ No newline at end of file +{{=records}} diff --git a/applications/examples/views/database_examples/register_product.html b/applications/examples/views/database_examples/register_product.html index eeebb2e8..a896cc63 100644 --- a/applications/examples/views/database_examples/register_product.html +++ b/applications/examples/views/database_examples/register_product.html @@ -1,6 +1,6 @@ -{{extend 'layout_examples/layout_civilized.html'}} +{{extend 'layout.html'}}

Product registration form

{{=form}}

Current products

-{{=records}} \ No newline at end of file +{{=records}} diff --git a/applications/examples/views/default/download.html b/applications/examples/views/default/download.html index fc1768da..bad4969f 100644 --- a/applications/examples/views/default/download.html +++ b/applications/examples/views/default/download.html @@ -16,13 +16,13 @@ For Windows For Windows - Mercurial Repository + Git Repository Download For Mac For Mac - Issue Tracker + Mercurial Repository Mercurial Repository @@ -34,7 +34,8 @@ Change Log Unittest Log - + Issue Tracker + diff --git a/applications/examples/views/default/examples.html b/applications/examples/views/default/examples.html index 8b66aab2..23b1cfd2 100644 --- a/applications/examples/views/default/examples.html +++ b/applications/examples/views/default/examples.html @@ -28,28 +28,28 @@

Example {{c=1}}{{=c}}{{c+=1}}

In controller: simple_examples.py {{=CODE(""" - def hello1(): - return "Hello World" - """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} +def hello1(): + return "Hello World" + """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}

If the controller function returns a string, that is the body of the rendered page.
Try it here: hello1

Example {{=c}}{{c+=1}}

In controller: simple_examples.py {{=CODE(""" - def hello2(): - return T("Hello World") - """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} +def hello2(): + return T("Hello World") + """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}

The function T() marks strings that need to be translated. Translation dictionaries can be created at /admin/default/design
Try it here: hello2

Example {{=c}}{{c+=1}}

In controller: simple_examples.py {{=CODE(""" - def hello3(): - return dict(message=T("Hello World")) - """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} +def hello3(): + return dict(message=T("Hello World")) + """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}} and view: simple_examples/hello3.html - {{=CODE(open(os.path.join(request.folder,'views/simple_examples/hello3.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} + {{=CODE(open(os.path.join(request.folder,'views/simple_examples/hello3.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}

If you return a dictionary, the variables defined in the dictionery are visible to the view (template).
Try it here: hello3

@@ -57,18 +57,18 @@

Example {{=c}}{{c+=1}}

In controller: simple_examples.py {{=CODE(""" - def hello4(): - response.view='simple_examples/hello3.html' - return dict(message=T("Hello World")) - """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} +def hello4(): + response.view='simple_examples/hello3.html' + return dict(message=T("Hello World")) + """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}

You can change the view, but the default is /[controller]/[function].html. If the default is not found web2py tries to render the page using the generic.html view.
Try it here: hello4

Example {{=c}}{{c+=1}}

In controller: simple_examples.py {{=CODE(""" - def hello5(): - return HTML(BODY(H1(T('Hello World'),_style="color: red;"))).xml() # .xml to serialize - """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} +def hello5(): + return HTML(BODY(H1(T('Hello World'),_style="color: red;"))).xml() # .xml to serialize + """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}

You can also generate HTML using helper objects HTML, BODY, H1, etc. Each of these tags is a class and the views know how to render the corresponding objects. The method .xml() serializes them and produce html/xml code for the page. Each tag, DIV for example, takes three types of arguments: