From 113095c3acc970d277d046bd345afd731088270c Mon Sep 17 00:00:00 2001
From: Massimo Di Pierro {{=records}} {{=records}} If the controller function returns a string, that is the body of the rendered page. The function T() marks strings that need to be translated. Translation dictionaries can be created at /admin/default/design If you return a dictionary, the variables defined in the dictionery are visible to the view (template).
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.
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: response.flash allows you to flash a message to the user when the page is returned. Use session.flash instead of response.flash to display a message after redirection. With default layout, you can click on the flash to make it disappear.
Here we are showing the request, session and response objects using the generic.html template.
You can do redirect.
You can raise HTTP exceptions to return an error page.
If an exception occurs (other than HTTP) a ticket is generated and the event is logged for the administrator. These tickets and logs can be accessed, reviewed and deleted at any later time.
You can serve other than HTML pages by changing the contenttype via the response.headers. The gluon.contenttype module can help you figure the type of the file to be served. NOTICE: this is not necessary for static files unless you want to require authorization.
If you are into Ajax, web2py includes gluon.contrib.simplejson, developed by Bob Ippolito. This module provides a fast and easy way to serve asynchronous content to your Ajax page. gluon.simplesjson.dumps(...) can serialize most Python types into JSON. gluon.contrib.simplejson.loads(...) performs the reverse operation.
web2py also includes gluon.contrib.pyrtf, developed by Simon Cusack and revised by Grant Edwards. This module allows you to generate Rich Text Format documents including colored formatted text and pictures. web2py includes gluon.contrib.rss2, developed by Dalke Scientific Software, which generates RSS2 feeds, and
gluon.contrib.feedparser, developed by Mark Pilgrim, which collects RSS and ATOM feeds. The above controller collects a slashdot feed and makes new one.
The markmin wiki markup is described here.
+def ajaxwiki_onclick():
+ return MARKMIN(request.vars.text).xml()
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
+ The markmin wiki markup is described here.
web2py also includes gluon.contrib.markdown.WIKI helper (markdown2) which converts WIKI markup to HTML following this syntax. In this example we added a fancy ajax effect. Click to count. The session.counter is persistent for this user and application. Every applicaiton within the system has its own separate session management.
A view (also known as template) is just an HTML file with {{...}} tags. You can put ANY python code into the tags, no need to indent but you must use pass to close blocks. The view is transformed into a python code and then executed. {{=a}} prints a.xml() or escape(str(a)).
You can do for and while loops.
You can do if, elif, else.
You can do try, except, finally.
You can write functions in HTML too.
The argument of {{=...}} is always escaped unless it is an object with a .xml() method such as link, A(...), a FORM(...), a XML(...) block, etc.
If you do not want to escape the argument of {{=...}} mark it as XML.
You can use BEAUTIFY to turn lists and dictionaries into organized HTML.
You can specify the layout file at the top of your view. civilized Layout file is a view that somewhere in the body contains {{include}}.
Same here, but using a different template. 'layout.html' is the default template, every application has a copy of it.
You can use HTML helpers like FORM, INPUT, TEXTAREA, OPTION, SELECT to build forms. The "value=" attribute sets the initial value of the field (works for TEXTAREA and OPTION/SELECT too) and the requires attribute sets the validators.
FORM.accepts(..) tries to validate the form and, on success, stores vars into form.vars. On failure the error messages are stored into form.errors and shown in the form.
Tables are created if they do not exist (try... except).
- Here "purchased" is an SQLQuery object, "db(purchased)" would be a SQLSet objects. A SQLSet object can be selected, updated, deleted. SQLSets can also be intersected. Allowed field types are string, integer, password, text, blob, upload, date, time, datetime, references(*), and id(*). The id field is there by default and must not be declared. references are for one to many and many to many as in the example above. For strings you should specify a length or you get length=32. This is a simple user registration form. SQLFORM takes a table and returns the corresponding entry form with validators, etc. SQLFORM.accepts is similar to FORM.accepts but, if form is validated, the corresponding insert is also performed. SQLFORM can also do update and edit if a record is passed as its second argument.
SQLTABLE instead turns a set of records (result of a select) into an HTML table with links as specified by its optional parameters.
The response.menu on top is just a variable used by the layout to make the navigation menu for all functions in this controller.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!)
-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 @@
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 @@
Change Log
Unittest Log
-
+ Issue Tracker
+
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')}}
Try it here: hello1Example {{=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')}}
Try it here: hello2Example {{=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')}}
Try it here: hello3Example {{=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')}}
Try it here: hello4Example {{=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')}}
@@ -80,54 +80,54 @@
Example {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def hello6():
- response.flash=T("Hello World in a flash!")
- return dict(message=T("Hello World"))
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def hello6():
+ response.flash=T("Hello World in a flash!")
+ return dict(message=T("Hello World"))
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: hello6Example {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def status():
- return dict(request=request,session=session,response=response)
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def status():
+ return dict(toobar=response.toolbar())
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: statusExample {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def redirectme():
- redirect(URL('hello3'))
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def redirectme():
+ redirect(URL('hello3'))
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: redirectmeExample {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def raisehttp():
- raise HTTP(400,"internal error")
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def raisehttp():
+ raise HTTP(400,"internal error")
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: raisehttpExample {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def raiseexception():
- 1/0
- return 'oops'
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def raiseexception():
+ 1/0
+ return 'oops'
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: raiseexceptionExample {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def servejs():
- import gluon.contenttype
- response.headers['Content-Type']=gluon.contenttype.contenttype('.js')
- return 'alert("This is a Javascript document, it is not supposed to run!");'
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def servejs():
+ import gluon.contenttype
+ response.headers['Content-Type']=gluon.contenttype.contenttype('.js')
+ return 'alert("This is a Javascript document, it is not supposed to run!");'
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: servejs
Try it here: makejsonExample {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def makertf():
- import gluon.contrib.pyrtf as q
- doc=q.Document()
- section=q.Section()
- doc.Sections.append(section)
- section.append('Section Title')
- section.append('web2py is great. '*100)
- response.headers['Content-Type']='text/rtf'
- return q.dumps(doc)
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def makertf():
+ import gluon.contrib.pyrtf as q
+ doc=q.Document()
+ section=q.Section()
+ doc.Sections.append(section)
+ section.append('Section Title')
+ section.append('web2py is great. '*100)
+ response.headers['Content-Type']='text/rtf'
+ return q.dumps(doc)
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: makertfExample {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def rss_aggregator():
- import datetime
- import gluon.contrib.rss2 as rss2
- import gluon.contrib.feedparser as feedparser
- d = feedparser.parse("http://rss.slashdot.org/Slashdot/slashdot/to")
-
- rss = rss2.RSS2(title=d.channel.title,
- link = d.channel.link,
- description = d.channel.description,
- lastBuildDate = datetime.datetime.now(),
- items = [
- rss2.RSSItem(
- title = entry.title,
- link = entry.link,
- description = entry.description,
- # guid = rss2.Guid('unkown'),
- pubDate = datetime.datetime.now()) for entry in d.entries]
- )
- response.headers['Content-Type']='application/rss+xml'
- return rss2.dumps(rss)
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def rss_aggregator():
+ import datetime
+ import gluon.contrib.rss2 as rss2
+ import gluon.contrib.feedparser as feedparser
+ d = feedparser.parse("http://rss.slashdot.org/Slashdot/slashdot/to")
+
+ rss = rss2.RSS2(title=d.channel.title,
+ link = d.channel.link,
+ description = d.channel.description,
+ lastBuildDate = datetime.datetime.now(),
+ items = [
+ rss2.RSSItem(
+ title = entry.title,
+ link = entry.link,
+ description = entry.description,
+ # guid = rss2.Guid('unkown'),
+ pubDate = datetime.datetime.now()) for entry in d.entries]
+ )
+ response.headers['Content-Type']='application/rss+xml'
+ return rss2.dumps(rss)
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: rss_aggregatorExample {{=c}}{{c+=1}}
In controller: simple_examples.py
{{=CODE("""
- def ajaxwiki():
- form=FORM(TEXTAREA(_id='text',_name='text'),
- INPUT(_type='button',_value='markmin',
- _onclick="ajax('ajaxwiki_onclick',['text'],'html')"))
- return dict(form=form,html=DIV(_id='html'))
+def ajaxwiki():
+ form=FORM(TEXTAREA(_id='text',_name='text'),
+ INPUT(_type='button',_value='markmin',
+ _onclick="ajax('ajaxwiki_onclick',['text'],'html')"))
+ return dict(form=form,html=DIV(_id='html'))
- def ajaxwiki_onclick():
- return MARKMIN(request.vars.text).xml()
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
-
Try it here: ajaxwikiSession Examples
@@ -202,12 +202,11 @@
Example {{=c}}{{c+=1}}
In controller: session_examples.py
{{=CODE("""
- def counter():
- if not session.counter: session.counter=0
- session.counter+=1
- return dict(counter=session.counter)
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: session_examples/counter.html
- {{=CODE(open(os.path.join(request.folder,'views/session_examples/counter.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def counter():
+ session.counter = (sesstion.counter or 0) + 1
+ return dict(counter=session.counter)
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: session_examples/counter.html
+ {{=CODE(open(os.path.join(request.folder,'views/session_examples/counter.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: counterExample {{=c}}{{c+=1}}
In controller: template_examples.py
{{=CODE("""
- def variables(): return dict(a=10, b=20)
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: template_examples/variables.html
- {{=CODE(open(os.path.join(request.folder,'views/template_examples/variables.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def variables():
+ return dict(a=10, b=20)
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: template_examples/variables.html
+ {{=CODE(open(os.path.join(request.folder,'views/template_examples/variables.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: variablesExample {{=c}}{{c+=1}}
In controller: template_examples.py
{{=CODE("""
- def test_for(): return dict()
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: template_examples/test_for.html
- {{=CODE(open(os.path.join(request.folder,'views/template_examples/test_for.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def test_for():
+ return dict()
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: template_examples/test_for.html
+ {{=CODE(open(os.path.join(request.folder,'views/template_examples/test_for.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: test_forExample {{=c}}{{c+=1}}
In controller: template_examples.py
{{=CODE("""
- def test_if(): return dict()
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: template_examples/test_if.html
- {{=CODE(open(os.path.join(request.folder,'views/template_examples/test_if.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def test_if():
+ return dict()
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: template_examples/test_if.html
+ {{=CODE(open(os.path.join(request.folder,'views/template_examples/test_if.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: test_ifExample {{=c}}{{c+=1}}
In controller: template_examples.py
{{=CODE("""
- def test_try(): return dict()
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: template_examples/test_try.html
- {{=CODE(open(os.path.join(request.folder,'views/template_examples/test_try.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def test_try():
+ return dict()
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: template_examples/test_try.html
+ {{=CODE(open(os.path.join(request.folder,'views/template_examples/test_try.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: test_tryExample {{=c}}{{c+=1}}
In controller: template_examples.py
{{=CODE("""
- def test_def(): return dict()
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: template_examples/test_def.html
- {{=CODE(open(os.path.join(request.folder,'views/template_examples/test_def.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def test_def():
+ return dict()
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: template_examples/test_def.html
+ {{=CODE(open(os.path.join(request.folder,'views/template_examples/test_def.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: test_defExample {{=c}}{{c+=1}}
In controller: template_examples.py
{{=CODE("""
- def escape(): return dict(message='text is escaped
')
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: template_examples/escape.html
- {{=CODE(open(os.path.join(request.folder,'views/template_examples/escape.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def escape():
+ return dict(message='text is escaped
')
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: template_examples/escape.html
+ {{=CODE(open(os.path.join(request.folder,'views/template_examples/escape.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: escapeExample {{=c}}{{c+=1}}
In controller: template_examples.py
{{=CODE("""
- def xml():
- return dict(message=XML('text is not escaped
'))
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: template_examples/xml.html
- {{=CODE(open(os.path.join(request.folder,'views/template_examples/xml.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def xml():
+ return dict(message=XML('text is not escaped
'))
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: template_examples/xml.html
+ {{=CODE(open(os.path.join(request.folder,'views/template_examples/xml.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: xmlExample {{=c}}{{c+=1}}
In controller: template_examples.py
{{=CODE("""
- def beautify(): return dict(message=BEAUTIFY(request))
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: template_examples/beautify.html
- {{=CODE(open(os.path.join(request.folder,'views/template_examples/beautify.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def beautify():
+ return dict(message=BEAUTIFY(request))
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: template_examples/beautify.html
+ {{=CODE(open(os.path.join(request.folder,'views/template_examples/beautify.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: beautifyExample {{=c}}{{c+=1}}
In controller: layout_examples.py
{{=CODE("""
- def civilized():
- response.menu=[['civilized',True,URL('civilized')],
- ['slick',False,URL('slick')],
- ['basic',False,URL('basic')]]
- response.flash='you clicked on civilized'
- return dict(message="you clicked on civilized")
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: layout_examples/civilized.html
- {{=CODE(open(os.path.join(request.folder,'views/layout_examples/civilized.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def civilized():
+ response.menu=[['civilized',True,URL('civilized')],
+ ['slick',False,URL('slick')],
+ ['basic',False,URL('basic')]]
+ response.flash='you clicked on civilized'
+ return dict(message="you clicked on civilized")
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: layout_examples/civilized.html
+ {{=CODE(open(os.path.join(request.folder,'views/layout_examples/civilized.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: civilizedExample {{=c}}{{c+=1}}
In controller: layout_examples.py
{{=CODE("""
- def slick():
- response.menu=[['civilized',False,URL('civilized')],
- ['slick',True,URL('slick')],
- ['basic',False,URL('basic')]]
- response.flash='you clicked on slick'
- return dict(message="you clicked on slick")
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: layout_examples/slick.html
- {{=CODE(open(os.path.join(request.folder,'views/layout_examples/slick.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def slick():
+ response.menu = [['civilized',False,URL('civilized')],
+ ['slick',True,URL('slick')],
+ ['basic',False,URL('basic')]]
+ response.flash = 'you clicked on slick'
+ return dict(message="you clicked on slick")
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: layout_examples/slick.html
+ {{=CODE(open(os.path.join(request.folder,'views/layout_examples/slick.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: slickExample {{=c}}{{c+=1}}
In controller: layout_examples.py
{{=CODE("""
- def basic():
- response.menu=[['civilized',False,URL('civilized')],
- ['slick',False,URL('slick')],
- ['basic',True,URL('basic')]]
- response.flash='you clicked on basic'
- return dict(message="you clicked on basic")
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: layout_examples/basic.html
- {{=CODE(open(os.path.join(request.folder,'views/layout_examples/basic.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def basic():
+ response.menu=[['civilized',False,URL('civilized')],
+ ['slick',False,URL('slick')],
+ ['basic',True,URL('basic')]]
+ response.flash='you clicked on basic'
+ return dict(message="you clicked on basic")
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: layout_examples/basic.html
+ {{=CODE(open(os.path.join(request.folder,'views/layout_examples/basic.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
Try it here: basicExample {{=c}}{{c+=1}}
In controller: form_examples.py
{{=CODE("""
- def form():
- form=FORM(TABLE(TR("Your name:",INPUT(_type="text",_name="name",requires=IS_NOT_EMPTY())),
- TR("Your email:",INPUT(_type="text",_name="email",requires=IS_EMAIL())),
- TR("Admin",INPUT(_type="checkbox",_name="admin")),
- TR("Sure?",SELECT('yes','no',_name="sure",requires=IS_IN_SET(['yes','no']))),
- TR("Profile",TEXTAREA(_name="profile",value="write something here")),
- TR("",INPUT(_type="submit",_value="SUBMIT"))))
- if form.accepts(request,session):
- response.flash="form accepted"
- elif form.errors:
- response.flash="form is invalid"
- else:
- response.flash="please fill the form"
- return dict(form=form,vars=form.vars)
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def form():
+ form=FORM(TABLE(TR("Your name:",INPUT(_type="text",_name="name",requires=IS_NOT_EMPTY())),
+ TR("Your email:",INPUT(_type="text",_name="email",requires=IS_EMAIL())),
+ TR("Admin",INPUT(_type="checkbox",_name="admin")),
+ TR("Sure?",SELECT('yes','no',_name="sure",requires=IS_IN_SET(['yes','no']))),
+ TR("Profile",TEXTAREA(_name="profile",value="write something here")),
+ TR("",INPUT(_type="submit",_value="SUBMIT"))))
+ if form.accepts(request,session):
+ response.flash="form accepted"
+ elif form.errors:
+ response.flash="form is invalid"
+ else:
+ response.flash="please fill the form"
+ return dict(form=form,vars=form.vars)
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
Try it here: formExample {{=c}}{{c+=1}}
in model: db.py
{{=CODE("""
- db=DAL('sqlite://storage.db')
+db.define_table(
+ 'person',
+ Field('name'),
+ Field('email'),
+ format = '%(name)s')
- db.define_table('users',
- Field('name'),
- Field('email'))
+# ONE (person) TO MANY (dogs)
- # ONE (users) TO MANY (dogs)
- db.define_table('dogs',
- Field('owner_id',db.users),
- Field('name'),
- Field('type'),
- Field('vaccinated','boolean',default=False),
- Field('picture','upload',default=''))
+db.define_table(
+ 'dog',
+ Field('owner_id', db.person),
+ Field('name'),
+ Field('type'),
+ Field('vaccinated', 'boolean', default=False),
+ Field('picture', 'upload', default=''),
+ format = '%(name)s')
- db.define_table('products',
- Field('name'),
- Field('description','text'))
+db.define_table(
+ 'product',
+ Field('name'),
+ Field('description', 'text'),
+ format = '%(name)s')
- # MANY (users) TO MANY (products)
- db.define_table('purchases',
- Field('buyer_id',db.users),
- Field('product_id',db.products),
- Field('quantity','integer'))
+# MANY (persons) TO MANY (purchases)
- purchased=((db.users.id==db.purchases.buyer_id)&(db.products.id==db.purchases.product_id))
+db.define_table(
+ 'purchase',
+ Field('buyer_id', db.person),
+ Field('product_id', db.product),
+ Field('quantity', 'integer'),
+ format = '%(quantity)s %(product_id)s -> %(buyer_id)s')
- 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)
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+purchased = \
+ (db.person.id==db.purchase.buyer_id)&\
+ (db.product.id==db.purchase.product_id)
+
+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)
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
+ Here "purchased" is an Query object, "db(purchased)" would be a Set objects. A Set object can be selected, updated, deleted. Sets can also be intersected. Allowed field types are string, integer, password, text, blob, upload, date, time, datetime, references(*), and id(*). The id field is there by default and must not be declared. references are for one to many and many to many as in the example above. For strings you should specify a length or you get length=32.
You can use db.tablename.fieldname.requires= to set restrictions on the field values. These restrictions are automatically converted into widgets when generating forms from the table with SQLFORM(db.tablename).
define_tables creates the table and attempts a migration if table has changed or if database name has changed since last time. If you know you already have the table in the database and you do not want to attempt a migration add one last argument to define_table migrate=False.Example {{=c}}{{c+=1}}
In controller: database_examples.py
{{=CODE("""
- response.menu=[['Register User',False,URL('register_user')],
- ['Register Dog',False,URL('register_dog')],
- ['Register Product',False,URL('register_product')],
- ['Buy product',False,URL('buy')]]
+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():
- ### create an insert form from the table
- form=SQLFORM(db.users)
- ### if form is correct, perform the insert
- if form.accepts(request,session):
- response.flash='new record inserted'
- ### and get a list of all users
- records=SQLTABLE(db().select(db.users.ALL))
- return dict(form=form,records=records)
- """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}and view: database_examples/register_user.html
- {{=CODE(open(os.path.join(request.folder,'views/database_examples/register_user.html'),'r').read(),language='html',link=URL(r=request,c='global',f='vars'),_class='boxCode')}}
+def register_person():
+ # create an insert form from the table
+ form = SQLFORM(db.person)
+
+ # if form correct perform the insert
+ if form.process().accepted:
+ response.flash = 'new record inserted'
+
+ # and get a list of all persons
+ records = SQLTABLE(db().select(db.person.ALL),headers='fieldname:capitalize')
+
+ return dict(form=form, records=records)
+ """.strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}and view: database_examples/register_person.html
+ {{=CODE(open(os.path.join(request.folder,'views/database_examples/register_person.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
- Try it here: register_user
Here is a dog registration form. Notice that the "image" (type "upload") field is rendered into a <INPUT type="file"> html tag. SQLFORM.accepts(...) handles the upload of the file into the uploads/ folder.
Try it here: register_dog
Nothing new here.
Try it here: register_product
Here is a rather sophisticated buy form. It checks that the buyer and the product are in the database and updates the corresponding record or inserts a new purchase. It also does a JOIN to list all purchases.
Try it here: buy
This is an update on an SQLSet. (db.purchase.id>0 identifies the set containing only table db.purchases.)
-
Try it here: reset_purchased
This controller allows users to download the uploaded pictures of the dogs. Remember the upload=URL(...'download'...) statement in the register_dog function. Notice that in the URL path /application/controller/function/a/b/etc a, b, etc are passed to the controller as request.args[0], request.args[1], etc. Since the URL is validated request.args[] always contain valid filenames and no '~' or '..' etc. This is useful to allow visitors to link uploaded files.
@@ -510,79 +519,79 @@The output of lambda:time.ctime() is cached in ram for 5 seconds. The string 'time' is used as cache key.
Try it here: cache_in_ram
The output of lambda:time.ctime() is cached on disk (using the shelve module) for 5 seconds.
Try it here: cache_on_disk
The output of lambda:time.ctime() is cached on disk (using the shelve module) and then in ram for 5 seconds. web2py looks in ram first and if not there it looks on disk. If it is not on disk it calls the function. This is useful in a multiprocess type of environment. The two times do not have to be the same.
Try it here: cache_in_ram_and_disk
Here the entire controller (dictionary) is cached in ram for 5 seconds. The result of a select cannot be cached unless it is first serialized into a table lambda:SQLTABLE(db().select(db.users.ALL)).xml(). You can read below for an even better way to do it. + import time + t=time.ctime() + return dict(time=t,link=A('click to reload',_href=URL(r=request)))""".strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}} +
Here the entire controller (dictionary) is cached in ram for 5 seconds. The result of a select cannot be cached unless it is first serialized into a table lambda:SQLTABLE(db().select(db.user.ALL)).xml(). You can read below for an even better way to do it.
Try it here: cache_controller_in_ram
Here the entire controller (dictionary) is cached on disk for 5 seconds. This will not work if the dictionary contains unpickleable objects.
Try it here: cache_controller_on_disk
response.render(d) renders the dictionary inside the controller, so everything is cached now for 5 seconds. This is best and fastest way of caching!
Try it here: cache_controller_and_view
The results of a select are complex unpickleable objects that cannot be cached using the previous method, but the select command takes an argument cache=(cache_model,time_expire) and will cache the result of the query accordingly. Notice that the key is not necessary since key is generated based on the database name and the select string.
Try it here: cache_db_select
The javascript function "ajax" is provided in "web2py_ajax.html" and included by "layout.html". It takes three arguments, a url, a list of ids and a target id. When called, it sends to the url (via a get) the values of the ids and display the response in the value (of innerHTML) of the target id.
Try it here: index
Try it here: flash
Try it here: fade
Using the Python doctest notation it is possible to write tests for all controller functions. Tests are then run via the administrative interface which generates a report. Here is an example of a test in the code: {{=CODE(""" - def index(): - ''' - This is a docstring. The following 3 lines are a doctest: - >>> request.vars.name='Max' - >>> index() - {'name': 'Max'} - ''' - return dict(name=request.vars.name) - """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} +def index(): + ''' + This is a docstring. The following 3 lines are a doctest: + >>> request.vars.name='Max' + >>> index() + {'name': 'Max'} + ''' + return dict(name=request.vars.name) +""".strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
It is very easy in web2py to stream large files. Here is an example of a controller that does so:
{{=CODE(""" - def streamer(): - import os - path=os.path.join(request.folder,'private','largefile.mpeg4') - return response.stream(open(path,'rb'),chunk_size=4096) - """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} +def streamer(): + import os + path=os.path.join(request.folder,'private','largefile.mpeg4') + return response.stream(open(path,'rb'),chunk_size=4096) +""".strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}By default all static files and files stored in 'upload' fields in the database are streamed when larger than 1MByte.
web2py automatically and transparently handles PARTIAL_CONTENT and RANGE requests. @@ -663,22 +672,22 @@Web2py has native support for the XMLRPC protocol. Below is a controller function "handler" that exposes two functions, "add" and "sub" via XMLRPC. The controller "tester" executes the two function remotely via xmlrpc.
{{=CODE(""" - from gluon.tools import Service - service = Service(globals()) +from gluon.tools import Service +service = Service(globals()) - @service.xmlrpc - def add(a,b): return a+b +@service.xmlrpc +def add(a,b): return a+b - @service.xmlrpc - def sub(a,b): return a-b +@service.xmlrpc +def sub(a,b): return a-b - def call(): return service() +def call(): return service() - def tester(): - import xmlrpclib - server=xmlrpclib.ServerProxy('http://hostname:port/app/controller/call/xmlrpc') - return str(server.add(3,4)+server.sub(3,4)) - """.strip(),language='web2py',link=URL(r=request,c='global',f='vars'),_class='boxCode')}} +def tester(): + import xmlrpclib + server=xmlrpclib.ServerProxy('http://hostname:port/app/controller/call/xmlrpc') + return str(server.add(3,4)+server.sub(3,4)) +""".strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}} diff --git a/applications/examples/views/default/index.html b/applications/examples/views/default/index.html index 36e4c67e..cb110915 100644 --- a/applications/examples/views/default/index.html +++ b/applications/examples/views/default/index.html @@ -43,11 +43,11 @@ {{end}} {{block right_sidebar}} -