Download - web2py:Web development like a boss

Transcript
Page 1: web2py:Web development like a boss

Web2py: Web development like a boss

Francisco Gama Tabanez Ribeiro

Sunday, December 11, 11

Page 2: web2py:Web development like a boss

Agenda

‣ my path on web dev - lessons learned

‣ web2py web framework:

‣ intro

‣ internals

‣ live demo - building a WiKi

‣ resources

Sunday, December 11, 11

Page 3: web2py:Web development like a boss

view source

Sunday, December 11, 11

Page 4: web2py:Web development like a boss

Sunday, December 11, 11

Page 5: web2py:Web development like a boss

Sunday, December 11, 11

Page 6: web2py:Web development like a boss

Sunday, December 11, 11

Page 7: web2py:Web development like a boss

1999 - Lisbon, Portugal

Sunday, December 11, 11

Page 8: web2py:Web development like a boss

Sunday, December 11, 11

Page 9: web2py:Web development like a boss

Sunday, December 11, 11

Page 10: web2py:Web development like a boss

10 1 11 01

010 0

1

Sunday, December 11, 11

Page 11: web2py:Web development like a boss

5 years later...Sunday, December 11, 11

Page 13: web2py:Web development like a boss

Perl?

• LUKE: Is Perl better than Python?

• YODA: No... no... no. Quicker, easier, more seductive.

• LUKE: But how will I know why Python is better than Perl?

• YODA: You will know. . .

When your code you try to read six months from now.

Sunday, December 11, 11

Page 14: web2py:Web development like a boss

Ruby?

Beautiful is better than ugly.

[...]

Although practicality beats purity.

from The Zen of Python

Sunday, December 11, 11

Page 15: web2py:Web development like a boss

God will love you anyway

Heroku

Rubinius

Sunday, December 11, 11

Page 16: web2py:Web development like a boss

Sunday, December 11, 11

Page 17: web2py:Web development like a boss

Sunday, December 11, 11

Page 18: web2py:Web development like a boss

?

Sunday, December 11, 11

Page 19: web2py:Web development like a boss

?

Sunday, December 11, 11

Page 20: web2py:Web development like a boss

lessons learned (1/2)

• rapid turnaround

• secure by design

• web development is mostly about visual UI’s

• relies mostly on user interaction & feedback

• convention over configuration

• flexible as in hackable

Sunday, December 11, 11

Page 21: web2py:Web development like a boss

lessons learned (2/2)

• fast and efficient but mostly scalable and stable

• different things come in different places

• plays well with others

• backward compatibility assured

• live community & support resources

• fun

Sunday, December 11, 11

Page 22: web2py:Web development like a boss

Sunday, December 11, 11

Page 23: web2py:Web development like a boss

Welcome to the club!

founder: Massimo Di Pierro

main contributors: +80

users: +2000

Sunday, December 11, 11

Page 24: web2py:Web development like a boss

Install and run...

Sunday, December 11, 11

Page 25: web2py:Web development like a boss

Install and run...

curl -O http://www.web2py.com/examples/static/web2py_src.zip

Sunday, December 11, 11

Page 26: web2py:Web development like a boss

why?• easy to run, install and play with

• python based

• web IDE included

• web based database admin

• no dependencies, no configuration required

• multiple platform (GAE, EC2, Jython...)

Sunday, December 11, 11

Page 27: web2py:Web development like a boss

why?

• Open source (LGPLv3 license)

• web2py applications have no license constraints

• web2py allows application bytecode compilation

• always backward compatible

• deployment-friendly...

Sunday, December 11, 11

Page 28: web2py:Web development like a boss

deployment..• always backward

compatible

• integrates well with web servers (cgi, fcgi, mod_python, mod_wsgi)

• error logging and ticketing support

• Database Abstraction Layer integrated

• integrated versioning

• integrated self-update capability

• multiple caching methods

• testing methods and debug shell

Sunday, December 11, 11

Page 29: web2py:Web development like a boss

what else?• secure (against XSS, Injection flaws, RFI)

• SSL and multiple authentication methods

• enforces good Software Engineering practices (MVC, Server-side form validation, postbacks...)

• Internationalization support

• HTML/XML, RSS/ATOM, RTF, PDF, JSON, AJAX (includes jQuery), XML-RPC, CSV, REST, WIKI, Flash/AMF, and Linked Data (RDF)

Sunday, December 11, 11

Page 30: web2py:Web development like a boss

Web basedAdmin Interface

Sunday, December 11, 11

Page 31: web2py:Web development like a boss

Hello World

def  hello1():                return  "Hello  World"

controllers/simple_examples.py

Sunday, December 11, 11

Page 32: web2py:Web development like a boss

Olá Mundo(Translation)

def  hello2():                return  T("Hello  World")

controllers/simple_examples.py

Sunday, December 11, 11

Page 33: web2py:Web development like a boss

Controller-View

def  hello3():                return  dict(message=T("Hello  World"))

{{extend  'layout.html'}}<h1>{{=message}}</h1>

controllers/simple_examples.py

views/hello3.html

Sunday, December 11, 11

Page 34: web2py:Web development like a boss

View

{{extend  'layout.html'}}<h1>{{=message}}</h1>

<html>    <head>        <title>example</title>          </head>    <body>          {{include}}      </body>  </html>

views/layout.html

views/hello3.html

Sunday, December 11, 11

Page 35: web2py:Web development like a boss

Web2py: flow

Sunday, December 11, 11

Page 36: web2py:Web development like a boss

Web2py: inside

Sunday, December 11, 11

Page 37: web2py:Web development like a boss

Web2py: inside

Python

Sunday, December 11, 11

Page 38: web2py:Web development like a boss

Web2py: inside

Python

rocket(SSL enabled web server)

API for third party servers(Apache,...)

Sunday, December 11, 11

Page 39: web2py:Web development like a boss

Web2py: inside

Python

rocket(SSL enabled web server)

API for third party servers(Apache,...)

Core libraries(HTTP request/response, session,

auth, services, DAL,...)

Contrib(simplejson, markdown, memcache, pyrtf, rss,...)

Sunday, December 11, 11

Page 40: web2py:Web development like a boss

Web2py: inside

Python

rocket(SSL enabled web server)

API for third party servers(Apache,...)

Core libraries(HTTP request/response, session,

auth, services, DAL,...)

User Applications

admin welcome user app

Contrib(simplejson, markdown, memcache, pyrtf, rss,...)

examples

Sunday, December 11, 11

Page 41: web2py:Web development like a boss

Web2py: inside

Python

rocket(SSL enabled web server)

API for third party servers(Apache,...)

Core libraries(HTTP request/response, session,

auth, services, DAL,...)

User Applications

admin welcome user app

Contrib(simplejson, markdown, memcache, pyrtf, rss,...)

examples

Sunday, December 11, 11

Page 42: web2py:Web development like a boss

web2py app inside

Sunday, December 11, 11

Page 43: web2py:Web development like a boss

web2py app inside

models

controllers

views

translations

static data

plugins & modules

appadmin

data

Sunday, December 11, 11

Page 44: web2py:Web development like a boss

web2py app inside

models

controllers

views

translations

static data

plugins & modules

appadmin

data

Sunday, December 11, 11

Page 45: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

web2py app inside

Sunday, December 11, 11

Page 46: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

db = SQLDB(‘sqlite://data.db’)

db.define_table(‘category’,Field(‘name’))

db.define_table(‘recipe’,Field(‘title’),Field(‘category’,db.category),Field(‘description’,‘text’))

web2py app inside

Sunday, December 11, 11

Page 47: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

db = SQLDB(‘sqlite://data.db’)

db.define_table(‘category’,Field(‘name’))

db.define_table(‘recipe’,Field(‘title’),Field(‘category’,db.category),Field(‘description’,‘text’))

SQlite

MySQL

PostgreSQL

Oracle

MSSQL

DB2

Firebird

MyBase

Informix

Google App Engine

Database types:

web2py app inside

Sunday, December 11, 11

Page 48: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

db = SQLDB(‘sqlite://data.db’)

db.define_table(‘category’,Field(‘name’))

db.define_table(‘recipe’,Field(‘title’),Field(‘category’,db.category),Field(‘description’,‘text’))

web2py app inside

Sunday, December 11, 11

Page 49: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

db = SQLDB(‘sqlite://data.db’)

db.define_table(‘category’,Field(‘name’))

db.define_table(‘recipe’,Field(‘title’),Field(‘category’,db.category),Field(‘description’,‘text’))

string

textinteger

double

datedatetime

time

booleanpassword

upload

blob

referencelist:string

list:interger

list:reference

Field types:

web2py app inside

Sunday, December 11, 11

Page 50: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

db = SQLDB(‘sqlite://data.db’)

db.define_table(‘category’,Field(‘name’))

db.define_table(‘recipe’,Field(‘title’),Field(‘category’,db.category),Field(‘description’,‘text’))

web2py app inside

Sunday, December 11, 11

Page 51: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

db = SQLDB(‘sqlite://data.db’)

db.define_table(‘category’,Field(‘name’))

db.define_table(‘recipe’,Field(‘title’),Field(‘category’,db.category),Field(‘description’,‘text’))

db.recipe.title.requires=IS_NOT_EMPTY()db.recipe.category.requires=IS_IN_DB(db,'category.id','category.name')db.category.name.requires=IS_NOT_IN_DB(db,'category.name')db.recipe.description.default='Fill your recipe in here...'

web2py app inside

Sunday, December 11, 11

Page 52: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

db = SQLDB(‘sqlite://data.db’)

db.define_table(‘category’,Field(‘name’))

db.define_table(‘recipe’,Field(‘title’),Field(‘category’,db.category),Field(‘description’,‘text’))

db.recipe.title.requires=IS_NOT_EMPTY()db.recipe.category.requires=IS_IN_DB(db,'category.id','category.name')db.category.name.requires=IS_NOT_IN_DB(db,'category.name')db.recipe.description.default='Fill your recipe in here...'

IS_DATEIS_DATETIME

IS_DATETIME_IN_RANGEIS_DATE_IN_RANGE

IS_DECIMAL_IN_RANGEIS_EMAIL

IS_EMPTY_ORIS_EQUAL_TO

IS_EXPRIS_FLOAT_IN_RANGE

IS_GENERIC_URLIS_HTTP_URL

IS_IMAGEIS_INT_IN_RANGE

IS_IN_DBIS_IN_SET

IS_IN_SUBSETIS_IPV4

IS_LENGTHIS_LIST_OFIS_LOWERIS_MATCH

IS_NOT_EMPTYIS_NOT_IN_DBIS_NULL_OR

IS_SLUGIS_STRONG

IS_TIMEIS_UPLOAD_FILENAME

IS_UPPERIS_URL

IS_ALPHANUMERIC

Validators:

web2py app inside

Sunday, December 11, 11

Page 53: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

web2py app inside

Sunday, December 11, 11

Page 54: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

def index(): return dict(recipes=db().select(db.recipe.ALL))

def add(): form=SQLFORM(db.recipe) if form.accepts(request.vars): redirect(URL(r=request,f='index')) return dict(form=form)

def show():recipes=db(db.recipe.id==request.args[0]).select()if not len(recipes):

redirect(URL(r=request,f='index')) return dict(recipe=recipes[0])

web2py app inside

Sunday, December 11, 11

Page 55: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

in file views/default/add.html:{{extend 'layout.html'}}<h1>{{T(‘New recipe’)}}</h1>{{=form}}

in file views/default/index.html:{{extend 'layout.html'}}<h1> {{T(‘List all recipes’)}} </h1><table>{{for recipe in recipes:}}<tr><td>{{=A(T(recipe.title),_href=URL(r=request,f='show', args=recipe.id))}}</td></tr>{{pass}}</table>

in file views/default/show.html:{{extend 'layout.html'}}<h1> {{=T(recipe.title)}} {{=db.recipe.category.represent(recipe.category)}}</h1><pre> {{=recipe.description}}</pre>

web2py app inside

Sunday, December 11, 11

Page 56: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

T(‘New recipe’)

T(‘List all recipes’)

T(recipe.title)

‘Nova receita’‘Nouvelle receité’...

‘Listar receitas’‘Lister receité’...

‘bitoque’‘duple cliché’...

web2py app inside

Sunday, December 11, 11

Page 57: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

images

css

js

web2py app inside

Sunday, December 11, 11

Page 58: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

ways to extend your apps:• modules are good way to import external code• plugins are applications subsets - a small application “inside” your application

web2py app inside

Sunday, December 11, 11

Page 59: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

data

web2py app inside

• databases (SQlite, MySQL, PostgreSQL, Oracle, MSSQL, DB2, Firebird, MyBase, Informix, Google App Engine)

• metadata for automatic migrations

• cache

Sunday, December 11, 11

Page 60: web2py:Web development like a boss

models

controllers

views

translations

static data

plugins & modules

appadmin

datadefault web based interface to your data

web2py app inside

Sunday, December 11, 11

Page 61: web2py:Web development like a boss

web2py URL parsinghttp://www.myhost.com:8000/myapp/default/index.html/a/b/c?name=Max

request.application = “myapp”request.controller = “default”

request.function = “index”request.extension = “html”

request.args = [‘a’,’b’,’c’]request.vars.name = “Max”

Environment variablesare in request.env

equivalent torequest.vars[‘name’]

Sunday, December 11, 11

Page 62: web2py:Web development like a boss

• functions in controllers return dicts() into views

• controller methods are exposed to views with the same name which is also used in the URL

• input validators (forms) are defined in the model as integrity constraints (requires)

• DAL automatically creates the id field in your tables

• model code has full application scope

remember..

Sunday, December 11, 11

Page 63: web2py:Web development like a boss

remember..• you can use your editor of choice

• you can use DAL separately

• in controller functions you can redefine the target view with response.view=”theme/myview.html”  

• web2py shell is your friend

• recommended - start your files with: #  coding:  utf8

Sunday, December 11, 11

Page 64: web2py:Web development like a boss

sessions

<html>      <head></head>      <body>            <h1>{{=message}}</h1>            <h2>Number  of  visits:  {{=counter}}</h2>      </body></html>

def  index():        session.counter  =  (session.counter  or  0)  +  1        return  dict(message="Hello  from  MyApp",  counter=session.counter)

inside controller:

inside view:

Sunday, December 11, 11

Page 65: web2py:Web development like a boss

Overview

Sunday, December 11, 11

Page 66: web2py:Web development like a boss

DAL select()

db(query).select(    field1,  field2,  ...,    left=[db.table.on(query)],    orderby=field|~field,    groupby=field|field    limitby=(0,10),    cache=(cache.ram,5000))

Examples:rows = db(db.recipe).select()

rows = db(db.recipe.id>0).select(db.recipe.title, db.recipe.category,orderby = db.recipe.category, distinct=True)

# christmas recipes from 2000query1 = db.recipe.created_in.year()>2000query2 = db.recipe_created_in.month()<10rows = db(query1 & query2).select()

Sunday, December 11, 11

Page 67: web2py:Web development like a boss

DAL select()

db(query).select(    field1,  field2,  ...,    left=[db.table.on(query)],    orderby=field|~field,    groupby=field|field    limitby=(0,10),    cache=(cache.ram,5000))

Examples:rows = db(db.recipe).select()

rows = db(db.recipe.id>0).select(db.recipe.title, db.recipe.category,orderby = db.recipe.category, distinct=True)

# christmas recipes from 2000query1 = db.recipe.created_in.year()>2000query2 = db.recipe_created_in.month()<10rows = db(query1 & query2).select()

equivalent to: rows = db(db.recipe.id>0).select(db.recipe.ALL)

Sunday, December 11, 11

Page 68: web2py:Web development like a boss

DAL select()

db(query).select(    field1,  field2,  ...,    left=[db.table.on(query)],    orderby=field|~field,    groupby=field|field    limitby=(0,10),    cache=(cache.ram,5000))

Examples:rows = db(db.recipe).select()

rows = db(db.recipe.id>0).select(db.recipe.title, db.recipe.category,orderby = db.recipe.category, distinct=True)

# christmas recipes from 2000query1 = db.recipe.created_in.year()>2000query2 = db.recipe_created_in.month()<10rows = db(query1 & query2).select()

equivalent to: rows = db(db.recipe.id>0).select(db.recipe.ALL)

queries can be combined with and(&), or(|) and not(~)

Sunday, December 11, 11

Page 69: web2py:Web development like a boss

DAL operations• Insert:

db.category.insert(name=‘soup’)

• Update:db(db.category.name==‘soup’).update(name=‘french soups’)

• Delete:db(db.category.name==‘french soups’).delete()

• Count:db(db.category.name.like(‘%soup%’)).count()

Sunday, December 11, 11

Page 70: web2py:Web development like a boss

DAL operations• Insert:

db.category.insert(name=‘soup’)

• Update:db(db.category.name==‘soup’).update(name=‘french soups’)

• Delete:db(db.category.name==‘french soups’).delete()

• Count:db(db.category.name.like(‘%soup%’)).count()

Other operators:.max(), .min(), .sum(), .belongs(), .like(),...

Sunday, December 11, 11

Page 71: web2py:Web development like a boss

DAL operations• Insert:

db.category.insert(name=‘soup’)

• Update:db(db.category.name==‘soup’).update(name=‘french soups’)

• Delete:db(db.category.name==‘french soups’).delete()

• Count:db(db.category.name.like(‘%soup%’)).count()

Other operations:transactions, inner joins, left outer joins, nested selects, self-references, many2many, ...

Other operators:.max(), .min(), .sum(), .belongs(), .like(),...

Sunday, December 11, 11

Page 72: web2py:Web development like a boss

Forms

• SQLFORM() / SQLFORM.factory()

• FORM()

• CRUD()

• <form></form>

Sunday, December 11, 11

Page 74: web2py:Web development like a boss

ComponentsLOAD()

{{=LOAD(‘controller’,‘function’,  ajax=True)}}

Sunday, December 11, 11

Page 75: web2py:Web development like a boss

ComponentsLOAD()

{{=LOAD(‘controller’,‘function’,  ajax=True)}}

supports auth signatures

Sunday, December 11, 11

Page 76: web2py:Web development like a boss

web2py Shell

python web2py.py -S myapplication -M

Sunday, December 11, 11

Page 77: web2py:Web development like a boss

HTML helpers

• BEAUTIFY(whatever)

• URL('application', 'controller', 'function', args=['x', 'y'], vars=dict(z='t'))

• much more... /application/controller/function/x/y?z=t

Sunday, December 11, 11

Page 78: web2py:Web development like a boss

Authentication & Authorization (Role-based)

Sunday, December 11, 11

Page 79: web2py:Web development like a boss

Authentication & Authorization (Role-based)doc_id  =  db.document.insert(body  =  'top  secret')  

agents  =  auth.add_group(role  =  'Secret  Agent')  

auth.add_membership(agents,  james_bond)

auth.add_permission(agents,  'read',  secrets)

auth.has_permission('read',  secrets,  doc_id,  james_bond)

auth.has_permission('update',  secrets,  doc_id,  james_bond)

auth.is_logged_in()

Sunday, December 11, 11

Page 80: web2py:Web development like a boss

Authentication & Authorization (Role-based)

@auth.requires_login()

@auth.requires_membership(agents)

@auth.requires_permission('read',  secrets)

@auth.requires_permission('delete',  'any  file')

@auth.requires(auth.user_id==1  or  request.client=='127.0.0.1')

@auth.requires_permission('add',  'number')

you also have:  agents  =  auth.add_group(role  =  'Secret  Agent')    auth.add_membership(agents,  james_bond)  auth.add_permission(agents,  'read',  secrets)

Sunday, December 11, 11

Page 81: web2py:Web development like a boss

@[email protected]@service.xmldef list_recipes(): return db(db.recipe).select()

@[email protected]@[email protected]@[email protected]@[email protected]@service.amfrpc3('domain')

Services

http://myhost/application/controller/list_recipes.xml

Sunday, December 11, 11

Page 82: web2py:Web development like a boss

@[email protected]@service.xmldef list_recipes(): return db(db.recipe).select()

@[email protected]@[email protected]@[email protected]@[email protected]@service.amfrpc3('domain')

Services

http://myhost/application/controller/list_recipes.xml.csv

....json

Sunday, December 11, 11

Page 83: web2py:Web development like a boss

@[email protected]@service.xmldef list_recipes(): return db(db.recipe).select()

@[email protected]@[email protected]@[email protected]@[email protected]@service.amfrpc3('domain')

Services

http://myhost/application/controller/list_recipes.xml.csv

....json

Sunday, December 11, 11

Page 84: web2py:Web development like a boss

Errors (ticketing)

errors/exceptions are logged into tickets

Sunday, December 11, 11

Page 85: web2py:Web development like a boss

Other

• Cron

• Routes

• Plugins

• Modules

• Grids

Caching in functions:  @cache("key",cache.ram,5000)  def  f():  return  dict()

Caching actions/views:  @cache(request.env.path_info,5000,cache.ram)  def  action():                    return  response.render(response.view,dict())

could be:cache.ram, cache.disk, cache.memcache

Sunday, December 11, 11

Page 86: web2py:Web development like a boss

demoWiki

Sunday, December 11, 11

Page 87: web2py:Web development like a boss

demoWiKi app(features)

• add pages

• show pages

• edit pages

• versioning

• authentication (local and remote)

• internationalization

• comments (with/without AJAX)

Sunday, December 11, 11

Page 88: web2py:Web development like a boss

demoWiKi app(model)

Sunday, December 11, 11

Page 89: web2py:Web development like a boss

web2py in real life

Francisco Costa

Sunday, December 11, 11

Page 90: web2py:Web development like a boss

Documentation (1/2)

• online book (www.web2py.com/book)

• book (printed version - amzn.to/vzjiqT)

• screencasts (www.vimeo.com)

• interactive examples (default app)

• AlterEgo (FAQ - www.web2py.com/AlterEgo)

Sunday, December 11, 11

Page 91: web2py:Web development like a boss

Documentation (2/2)

• epydoc (www.web2py.com/examples/static/epydoc/)

• API:(www.web2py.com/book/default/chapter/04#API)

Sunday, December 11, 11

Page 92: web2py:Web development like a boss

Community (1/2)

• free web2py appliances (www.web2py.com/appliances)

• code snippets (www.web2pyslices.com)

• groups:• users - http://groups.google.com/group/web2py/

• developers - http://groups.google.com/group/web2py-developers

Sunday, December 11, 11

Page 93: web2py:Web development like a boss

Community (2/2)

• #web2py (IRC channel at irc.freenode.net)

• twitter (http://twitter.com/web2py)

• user voice (http://web2py.uservoice.com)

• web2py websites (www.web2py.com/poweredby)

• web2py plugins (www.web2py.com/plugins/)

Sunday, December 11, 11

Page 94: web2py:Web development like a boss

Thank you

childish wont-let-go nickname: blackthorne

blackthorne (geek) bthorne_daily (social)

[email protected] (PGP key: 0xBDD20CF1)

http://www.digitalloft.org (homepage)

Sunday, December 11, 11

Page 95: web2py:Web development like a boss

web2py app defaults• menu

• web2py_ajax (jQuery)

• auth, mail, download and services

• english default lang translation

• generic view

Sunday, December 11, 11