Web2py: Desenvolvimento Ágil de Aplicações Web com Python

Post on 19-May-2015

2.035 views 38 download

description

Slides para apresentação de minicurso na FATEPI.

Transcript of Web2py: Desenvolvimento Ágil de Aplicações Web com Python

Desenvolvimento Ágil de Aplicações Web com Pythonpor Cláudio Torcato

terça-feira, 22 de novembro de 2011

terça-feira, 22 de novembro de 2011

História

Lançada em 2007

Massimo di Pierro, professor da Universidade DePaul, Chicago

Objetivos principais:

Fácil uso, desenvolvimento rápido e segurança

Versão atual: 1.99.2 (26.09.11)

terça-feira, 22 de novembro de 2011

InspiraçõesRuby on Rails

Desenvolvimento rápido

MVC Design

Django

Geração de formulários a partir de tabelas do banco de dados

Coleção de validadores extensíveis

terça-feira, 22 de novembro de 2011

CaracterísticasSem necessidade de instalação e configuração

Interface Web para Manutenção, Deployment e Desenvolvimento

Sistema de Ticketing

Framework Full-Stack

Retrocompatibilidade garantida

Open Source

terça-feira, 22 de novembro de 2011

Administração Web Based

Gerenciar aplicações

Criar aplicações

Desenvolver aplicações

Testar e Debugar

Integração com Mercurial

terça-feira, 22 de novembro de 2011

Arquitetura: MVC

terça-feira, 22 de novembro de 2011

Arquitetura

terça-feira, 22 de novembro de 2011

Controller

terça-feira, 22 de novembro de 2011

Estrutura

terça-feira, 22 de novembro de 2011

Default.py

terça-feira, 22 de novembro de 2011

Request

http://localhost:8000/a/c/f.html/x/y/z?p=1&q=2

request.args = [ 'x', 'y', 'z' ]

request.vars = { 'p' : 1, 'q' : 2 }

request.application = 'a'

request.controller = 'c'

request.function = 'f'

terça-feira, 22 de novembro de 2011

Usando Request

def variaveis(): vars = request.vars args = request.args return dict(vars = vars, args = args)

def primeiro_argumento(): variavel = request.args(0) return dict(var=variavel)

terça-feira, 22 de novembro de 2011

Session

session.variavel = "Oinc"

session.forget()

session.connect(request, response, db, masterapp=None)

def contador(): if session.cont: session.cont = session.cont+1 else: session.cont = 1 return dict( contador = session.cont )

terça-feira, 22 de novembro de 2011

Response

response.body

response.cookies

response.flash

response.headers

response.render(view, vars)

response.view

terça-feira, 22 de novembro de 2011

URL

URL('f') -- /[application]/[controller]/f

Suporte a mapeamento de URL e mapeamento reverso

Redefine o mapeamento de URLs externas

URL('a', 'c', 'f', args=['x', 'y'], vars={ z : 't' })

terça-feira, 22 de novembro de 2011

HTTP and Redirect

raise HTTP(400, "mensagem de erro")

redirect('http://www.web2py.com')

redirect(URL('index', args=(1,2,3),vars=dict(a='b')))

terça-feira, 22 de novembro de 2011

i18n e l10n

Arquivos de linguagem

O objeto T é uma instância global do tradutor de linguagem

Constantes String deveriam ser marcadas por T

Exemplo: T("Hello World")

terça-feira, 22 de novembro de 2011

View

terça-feira, 22 de novembro de 2011

Estrutura

terça-feira, 22 de novembro de 2011

Template Language

Python embutido em HTML

Código python entre {{ }}

Sem restrições à linguagem

Blocos de código finalizados por pass

terça-feira, 22 de novembro de 2011

{{if request.args(0): response.write('existe')else: response.write('não existe')pass}}

Exemplos

terça-feira, 22 de novembro de 2011

<html><body>{{ for x in range(10):}} {{=x}}hello<br/>{{ pass }}</body></html>

response.write("<html><body>", escape=False)for x in range(10): response.write(x) response.write("hello<br/>", escape=False)response.write("</body></html>", escape=False)

Geração da View

terça-feira, 22 de novembro de 2011

{{=variavel}}

response.write(x, escape=True)

Escaped por padrão

Se o objeto tem o método .xml(), ele é chamado e o escaping é ignorado

Senão usa o método __str__ para serializar

terça-feira, 22 de novembro de 2011

HTML Helpers

Classes usadas para construir HTML programaticamente

Helpers: A, B, BEAUTIFY, BR, CENTER, CODE, DIV, EM, EMBED, FIELDSET, FORM, H1, H2, H3, H4, H5, H6, HEAD, HR, I, IFRAME, IMG, INPUT, LABEL, LEGEND, LI, LINK, OL, UL, MARKMIN, MENU, META, OBJETCT, ON, OPTION, P, PRE, etc.

terça-feira, 22 de novembro de 2011

Exemplo de uso do Helper

{{=DIV(B(I('hello','<world>'))), _class="myclass") }}

<div class="myclass"> <b><i>hello &lt;world&gt;</i></b></div>

terça-feira, 22 de novembro de 2011

Page Layout

{{extend 'layout.html'}}<h1>Hello World</h1>{{include 'page.html'}}

<html><head><title>Page Title</title></head><body> {{include}}</body></html>

layout.html

index.html

terça-feira, 22 de novembro de 2011

Exemplo

def lista(): return dict(numeros = range(30))

<ul>{{ for numero in numeros: }} <li> {{=numero }} </li>{{ pass }}</ul>

controllers/visao.py

views/visao/lista.html

terça-feira, 22 de novembro de 2011

Model

terça-feira, 22 de novembro de 2011

Estrutura

terça-feira, 22 de novembro de 2011

Responsabilidades do Model

Acessar o Banco

Mapear Objetos e Tabelas

Gerar SQL dinamicamente

Validar campos das tabelas e formulários

terça-feira, 22 de novembro de 2011

Database Abstraction Layer - DAL

“An API that maps Python objects into database objects such as queries, tables, and records.”

Adapdadores para cada dialeto SQL

db = DAL("string de conexão")

terça-feira, 22 de novembro de 2011

String de Conexão

SQLite sqlite://storage.dbMySQL mysql://username:password@localhost/

testPostgreSQL postgres://username:pass@localhost/testMSSQL mssql://username:pass@localhost/testFirebird firebird://username:pass@localhost/testOracle oracle://username/pass@testDB2 db2://username:pass@testIngres ingres://username:pass@localhost/testInformix informix://username:pass@testGoogle App Engine gae

terça-feira, 22 de novembro de 2011

Table

db.define_table('pessoas', Field('nome'), Field('casado','boolean',default=False), Field('genero'), Field('data_nascimento','date',label='Data de Nascimento'))

db.pessoas.genero.requires = IS_IN_SET(['M','F','?'])

terça-feira, 22 de novembro de 2011

Tipos de Campos

terça-feira, 22 de novembro de 2011

Migrations

Alterações na definição de uma tabela no DAL refletirá no banco de dados

Tais mudanças são registradas em logs

db = DAL('sqlite://storage.db', migrate = False)

terça-feira, 22 de novembro de 2011

Métodos de Table

db.pessoas.insert(nome='Helena')

db.pessoas.truncate()

db.pessoas.bulk_insert({'nome':'Ana','sexo':'F'})

terça-feira, 22 de novembro de 2011

Query

Objeto que representa a cláusula “where” do SQL.

query = (db.pessoas.nome == 'Alex')

terça-feira, 22 de novembro de 2011

Set

Representa um conjunto de registros

Alguns métodos: count, select, update, delete

Exemplo: meu_set = db(query)

rows = meu_set.select()

meu_set.update(nome='Eloah')

meu_set.delete()

terça-feira, 22 de novembro de 2011

Rows

Resultado do comando select

class gluon.sql.Rows

Objeto iterável cujos elementos são objetos Row (gluon.sql.Row)

Objetos Row são parecidos com dicionários mas seus elementos podem ser acessados como atributos

terça-feira, 22 de novembro de 2011

Exemplo de Rows e Row

def solteiros(): query = (db.pessoas.casado == False) linhas = db(query).select() return dict( linhas = linhas)

<h2>Lista de Solteiros</h2><ul> {{ for solteiro in linhas: }} <li> {{=solteiro.nome }} {{ pass }}</ul>

controller

view

solteiro['nome']solteiro('pessoas.nome')

terça-feira, 22 de novembro de 2011

Selects Recursivos

db.define_table('caes', Field('nome'), Field('dono', db.pessoas))

caes = db(db.caes).select()

for cao in caes:print 'Nome do Dono:', cao.dono.nome

terça-feira, 22 de novembro de 2011

Select: argumentos opcionais

orderby

groupby

limitby

distinct

rows = db(db.pessoas).select(orderby=db.pessoas.nome)

terça-feira, 22 de novembro de 2011

Operadores Lógicos

rows = db((db.pessoas.nome == 'Alex') & (db.pessoas.idade > 18)).select()

rows = db((db.pessoas.nome == 'Alex') | (db.pessoas.idade > 18)). select()

rows = db(db.pessoas.nome != 'Alex').select()

terça-feira, 22 de novembro de 2011

Campos Computadosfrom datetime import date

def idade(tabela): niver = tabela.data_nascimento hoje = date.today() return niver.year - hoje.year

db.define_table('pessoas', Field('nome'), Field('data_nascimento','date'), Field('idade', compute = idade))

terça-feira, 22 de novembro de 2011

Campos Virtuais

Não alocados no BD

Computados a cada consulta no banco

class VirtualPessoa(object): def idade(self): return date.today().year - self.pessoas.data_nascimento.year

db.pessoas.virtualfields.append(VirtualPessoa())

terça-feira, 22 de novembro de 2011

Update

obj = db.pessoas(2)obj.update_record(nome='Edna')

db(db.pessoas.data_nascimento.year() > 1990). update(db.pessoas.cidade_natal = 'Teresina')

db.pessoas[ 2 ]db(db.pessoas.id == 2).select().first()

terça-feira, 22 de novembro de 2011

Joins

Inner Join

Left Outer Join

db(db.pessoas.id == db.caes.dono).select()

db().select(db.pessoas.ALL, db.caes.ALL, left=db.caes.on(db.pessoas.id==db.caes.dono))

terça-feira, 22 de novembro de 2011

Visualizando o SQL

print db.pessoas._insert(nome='Daniel')

print db(db.pessoas)._count()

print db(db.pessoas.idade < 19)._select()

print db(db.pessoas.idade == 20)._delete()

print db(db.pessoas.idade == 20)._update()

terça-feira, 22 de novembro de 2011

Auth

Role Based Access Control (RBAC)

Auth implementa RBAC

Tabelas:

auth_user, auth_group, auth_membership, auth_permission, auth_event

Decorators são usados para restringir acesso a funções por login, membership ou permissions

terça-feira, 22 de novembro de 2011

Authentication

Métodos de login:

tabela auth_user

Google, PAM, LDAP, Facebook, LinkedIn, OpenID, OAuth, etc.

terça-feira, 22 de novembro de 2011

Auth Decorators

@auth.requires_login()def function_um(): return "requer login"

@auth.requires_membership("agentes")def function_dois(): return "você é um agente"

@auth.requires_permission('read', db.documentos)def function_tres(): return "você pode ler documentos secretos"

terça-feira, 22 de novembro de 2011

Forms

FORM

SQLFORM

SQLFORM.factory

CRUD

terça-feira, 22 de novembro de 2011

FORM

def formulario(): form = FORM('Seu nome:', INPUT(_name='nome'), INPUT(_type='submit')) return dict(form=form)

{{=form}}

terça-feira, 22 de novembro de 2011

FORMValidação e processamento do Formulário

def formulario2(): form=FORM('Seu nome:', INPUT(_name='nome', requires=IS_NOT_EMPTY()), INPUT(_type='submit')) if form.process().accepted: response.flash = 'formulário aceito' elif form.errors: response.flash = 'formulário tem erros' else: response.flash = 'preencha o formulário' return dict(form=form)

terça-feira, 22 de novembro de 2011

SQLFORM

def formulario(): form = SQLFORM(db.pessoas) if form.process().accepted: response.flash = 'form aceito.' elif form.errors: response.flash = 'form tem erro.' else: response.flash = 'preencha form.' return dict(form=form)

terça-feira, 22 de novembro de 2011

SQLFORM.factory

terça-feira, 22 de novembro de 2011

CRUD

API recente

Simplifica o uso do SQLFORM por incorporar diversas atividades numa única função

Precisa ser importada

Deve ser ligada a um banco de dados

from gluon.tools import Crudcrud = Crud(db)

terça-feira, 22 de novembro de 2011

Métodos CRUDcrud.tables()

crud.create(db.nome_tabela)

crud.read(db.nome_tabela, id)

crud.update(db.nome_tabela, id)

crud.delete(db.nome_tabela, id)

crud.select(db.nome_tabela, query)

crud.search(db.nome_tabela)

crud()

terça-feira, 22 de novembro de 2011

Funções com CRUD

def create_cao(): form = crud.create(db.caes) return dict(form = form)

def update_cao(): form = crud.update(db.caes, request.args(0)) return dict(form = form)

terça-feira, 22 de novembro de 2011

Validadores

Classes usadas para validar entrada de campos (incluindo forms gerados de tabelas)

Podem ser usadas em Fields e em Forms

Sempre atribuídos usando o atributo requires de um campo

terça-feira, 22 de novembro de 2011

Lista de Validadores

IS_ALPHANUMERIC, IS_DATE, IS_DATE_IN_RANGE, IS_DATETIME, IS_DATETIME_IN_RANGE, IS_DECIMAL_IN_RANGE, IS_EMAIL, IS_EXPR, IS_FLOAT_IN_RANGE, IS_IN_SET, IS_LENGTH, IS_LIST_OF, IS_LOWER, IS_URL, IS_STRONG, IS_EMPTY_OR, CLEANUP, CRYPT

terça-feira, 22 de novembro de 2011

Services

Sistema de software projetado para suportar a interação máquina-máquina numa rede

Suporte a XML, JSON, RSS, CSV, XMLRPC, JSONRPC, AMFRPC e SOAP

Modos de suporte:

Renderizar a saída de uma função

Remote Procedure Calls

terça-feira, 22 de novembro de 2011

Generic Views

default/contador.xml procura views/default/contador.xml

Não encontrando, procura views/default/generic.xml

Generics para JSON, PDF, RSS, XML

terça-feira, 22 de novembro de 2011

Remote Procedure Calls

Web2py prover mecanismo para tornar qualquer função um web service

O que precisamos:

instanciar o objeto service

expor um manipulador de serviços no controller

decorar a função que será exposta como um serviço

terça-feira, 22 de novembro de 2011

Service Decorator

terça-feira, 22 de novembro de 2011

Do que não falamosURL Rewrite

Roteamento de Erros

Tarefas em background

Pyjamas

Blocks in Views

Caching

Exportação e Importação de Dados

Central Authentication Service

jQuery e Ajax

Deploy em Servidores de Produção

Escalabidade

Google App Engine

Componentes e Plugins

terça-feira, 22 de novembro de 2011