Upload
chackero
View
2.035
Download
38
Embed Size (px)
DESCRIPTION
Slides para apresentação de minicurso na FATEPI.
Citation preview
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
Roteamento de URL
http://localhost:8080/minicurso/default/index.html
padrão
init
default
index
html
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 <world></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
Referências
Web2py: http://www.web2py.com
web2py-users-brazil: https://groups.google.com/group/web2py-users-brazil?hl=pt-BR
The Official Web2py Book: http://www.web2py.com/book
http://www.infoworld.com/d/application-development/pillars-python-six-python-web-frameworks-compared-169442
terça-feira, 22 de novembro de 2011