O que é o Web2py?

web2py tag cloud

É uma framework open-source completa, escrita em Python, orientada para programação de aplicações WEB seguras, de uma forma ágil e rápida.

História

  • Final de 2007
  • Massimo Di Pierro
  • Universidade Depaul, Chicago
  • Versão 2.4.2 / March 4, 2013
  • 100+ colaboradores
  • Comunidade 4700+

Características

  • Não requer instalação
  • Multiplataforma (Linux, Mac, Win, Android)
  • Compatibilidade reversa
  • Servidor web integrado - Rocket
  • Multiplas Base de Dados (SQLite, MySQL, SQLServer, PostgreSQL, MongoDb, CouchDb, GAP Datastore, etc)
  • Multiplos Servidores WEB (Apache, Amazon, Cherokee, Google AppEngine, Lighttpd, nginx, etc)
  • Seguro (Cross Site Scripting, Injection Flaws, and Malicious File Execution)
  • Poliglota (RSS/ATOM, HTML/XML, JSON, PDF, AJAX, XML-RPC, Flash/AMF, WIKI, RTF, REST, CSV, Linked Data (RDF))
  • Multiplas aplicações (Cooperação)
  • CRUD's
  • Cron, Scheduler
  • Logging

MVC

web2py routing

Model

Database Abstraction Layer

                    db = DAL('sqlite://storage.db')

                    db.define_table('pessoas',
                        Field('nome', 'string', required = True),
                        Field('idade', 'integer'),
                        Field('data_registo', 'datetime', default = request.now),
                        Field('activo', 'boolean', default = True),
                    )
                    

Inserir, Seleciona, Atualizar, Apagar

                    pessoa_id = db.pessoas.insert(nome='Alexandre')

                    rows = db(db.pessoas.idade >= 18).select()
                    for row in rows:
                        print row.nome

                    row = db(db.pessoas.id == 2).select().first()
                    row.update_record(nome='Sofia')
                    db(db.pessoa.id == 2).update(name='Carolina')

                    db(db.pessoa.id > 30).delete()
                    

Controller

    def criar_pessoa():
        """retorna formulario para inserir nova pessoa"""
        formulario = crud.create(db.pessoas)
        return dict(formulario=formulario)

    def mostra_pessoa():
        """retorna dados de uma pessoa"""
        pessoa_id = request.vars.id  # http://dominio/aplicacao/pessoal/mostra_pessoa?id=23
        pessoa_id = request.args(0)  # http://dominio/aplicacao/pessoal/mostra_pessoa/23
        pessoa = db(db.pessoas.id == pessoa_id).select().first()
        if pessoa:
            nome = pessoa.nome
            idade = pessoa.idade
            return dict(nome=nome, idade=idade)
        else:
            session.flash = T('pessoa não encontrada')
            redirect(URL(application='init', controller='default', function='index',
                         args=['ola', 'mundo'], vars=dict(ola='mundo', foo='bar')
                     )
            )
                    

View

        {{extend 'layout.html'}}
        <h2>{{=T('lista de pessoas'.capitalize())}}</h2>
        <div id="lista_pessoas">
            <table>
            {{for pessoa in pessoas:}}
                <tr>
                    <td>{{=pessoa.nome}} - {{=pessoa.idade}}</td>
                    {{if idade >= 65:}}
                    <td>REFORMADO</td>
                    {{pass}}
                </tr>
            {{pass}}
            </table>
            <div>{{=T('Há %s %%{Pessoa}', symbols=len(pessoas))}}</div>
        </div>
                    

Remote procedure calls

            @service.run
            @service.xml
            @service.json
            @service.rss
            @service.csv
            @service.xmlrpc
            @service.jsonrpc
            @service.jsonrpc2
            @service.amfrpc3('domain')
            @service.soap('FunctionName',returns={'result':type},args={'param1':type,})
                    

Restful Web Services

            http://127.0.0.1/myapp/default/api/person
            http://127.0.0.1/myapp/default/api/persons.json

            @request.restful()
            def api():
                response.view = 'generic.json'
                def GET(tablename,id):
                    if not tablename=='person': raise HTTP(400)
                    return dict(person = db.person(id))
                def POST(tablename,**fields):
                    if not tablename=='person': raise HTTP(400)
                    return db.person.validate_and_insert(**fields)
                return locals()
                    

Auth

                        from gluon.tools import Auth
                        auth = Auth(db)
                        auth.define_tables()
                    
                        @auth.requires_login()
                        @auth.requires_membership(...)
                        @auth.requires_permission(...)
                        http://.../[app]/default/user/register
                        http://.../[app]/default/user/login
                        http://.../[app]/default/user/logout
                        http://.../[app]/default/user/profile
                        http://.../[app]/default/user/change_password
                        http://.../[app]/default/user/verify_email
                        http://.../[app]/default/user/retrieve_username
                        http://.../[app]/default/user/request_reset_password
                        http://.../[app]/default/user/reset_password
                        http://.../[app]/default/user/impersonate
                        http://.../[app]/default/user/groups
                        http://.../[app]/default/user/not_authorized
                    

SMTP e Gmail, X509, OAuth2.0 e Facebook, LDAP, LinkedIn, PAM, Google App Engine, OpenID

API

  • Request
  • Response
  • Session
  • Cache (cache.ram(), cache.disk())
  • T (internationalization, plural)
  • Helpers
            XML, URL, BEAUTIFY

            A, B, BODY, BR, CENTER, CODE, COL, COLGROUP,
            DIV, EM, EMBED, FIELDSET, FORM, H1, H2, H3, H4, H5, H6,
            HEAD, HR, HTML, I, IFRAME, IMG, INPUT, LABEL, LEGEND,
            LI, LINK, OL, UL, META, OBJECT, OPTION, P, PRE,
            SCRIPT, OPTGROUP, SELECT, SPAN, STYLE,
            TABLE, TAG, TD, TEXTAREA, TH, THEAD, TBODY, TFOOT,
            TITLE, TR, TT, URL, XHTML, xmlescape, embed64

            CAT, MARKMIN, MENU, ON
                    

API

  • Forms
  • Tables
            SQLFORM (SQLFORM.factory, SQLFORM.grid, SQLFORM.smartgrid)
                    
  • Validators
            CLEANUP, CRYPT, IS_ALPHANUMERIC, IS_DATE_IN_RANGE, IS_DATE,
            IS_DATETIME_IN_RANGE, IS_DATETIME, IS_DECIMAL_IN_RANGE,
            IS_EMAIL, IS_EMPTY_OR, IS_EXPR, IS_FLOAT_IN_RANGE, IS_IMAGE,
            IS_IN_DB, IS_IN_SET, IS_INT_IN_RANGE, IS_IPV4, IS_LENGTH,
            IS_LIST_OF, IS_LOWER, IS_MATCH, IS_EQUAL_TO, IS_NOT_EMPTY,
            IS_NOT_IN_DB, IS_NULL_OR, IS_SLUG, IS_STRONG, IS_TIME,
            IS_UPLOAD_FILENAME, IS_UPPER, IS_URL
                    

Routing

Dispatching

web2py routing

Parameter-based system

Routing

                    routers = dict(
                        BASE = dict(
                            applications = ['admin', 'api', 'blog', 'tymr', 'oauth2'],
                            default_application = 'tymr',
                            default_controller = 'default',
                            default_function = 'index',
                            root_static = ['favicon.ico', 'robots.txt'],
                            domains = {
                                'blog.tymr.com':    'blog',
                                'tymr.com':         'tymr',
                            },
                        ),
                        tymr = dict(
                            functions = dict(
                                user = ['show', 'settings', 'update', 'view'],
                                venue = ['create', 'show', 'edit', 'update'],
                            ),
                            default_controller = 'default',
                            default_function = dict(
                                user = 'index',
                                venue = 'show',
                            ),
                        ),
                    )
                    

Pattern-based system

Routing

                    routes_in = (
                        ('/admin/$anything', '/admin/$anything'),
                        ('/static/$anything', '/myapp/static/$anything'),
                        ('/appadmin/$anything', '/myapp/appadmin/$anything'),
                        ('/robots.txt', '/myapp/static/robots.txt'),
                    )

                    routes_out = [(x, y) for (y, x) in routes_in[:-2]]

                    routes_onerror = [
                        ('init/400', '/init/default/login'),
                        ('init/*', '/init/static/fail.html'),
                        ('*/404', '/init/static/cantfind.html'),
                        ('*/*', '/init/error/index')
                    ]
                    

Administração - Demo

Organização da Applicação

web2py routing

Brindes

  • One Click Upgrade
  • Exportar para binário
  • WingIDE, Rad2Py e Eclipse
  • SQLDesigner
  • Publicar pastas
  • Testes unitários
  • Geocoding
  • Paginação
  • Populate
  • Pagamentos - Paypal, Google Wallet, Stripe, Authorize.Net
  • Dropbox, Twitter
  • Emails e SMS

Documentação

Kickstarter

Real Python for Web Development, featuring web2py

Prémio

InfoWorld - web2py technology of the year 2012