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

2,862 views

Published on

Slides para apresentação de minicurso na FATEPI.

Published in: Technology

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

  1. 1. Desenvolvimento Ágil de Aplicações Web com Python por Cláudio Torcatoterça-feira, 22 de novembro de 2011
  2. 2. terça-feira, 22 de novembro de 2011
  3. 3. 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
  4. 4. Inspirações Ruby 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íveisterça-feira, 22 de novembro de 2011
  5. 5. Características Sem necessidade de instalação e configuração Interface Web para Manutenção, Deployment e Desenvolvimento Sistema de Ticketing Framework Full-Stack Retrocompatibilidade garantida Open Sourceterça-feira, 22 de novembro de 2011
  6. 6. Administração Web Based Gerenciar aplicações Criar aplicações Desenvolver aplicações Testar e Debugar Integração com Mercurialterça-feira, 22 de novembro de 2011
  7. 7. Arquitetura: MVCterça-feira, 22 de novembro de 2011
  8. 8. Arquiteturaterça-feira, 22 de novembro de 2011
  9. 9. Controllerterça-feira, 22 de novembro de 2011
  10. 10. Estruturaterça-feira, 22 de novembro de 2011
  11. 11. Default.pyterça-feira, 22 de novembro de 2011
  12. 12. Roteamento de URL http://localhost:8080/minicurso/default/index.html padrão init default index htmlterça-feira, 22 de novembro de 2011
  13. 13. 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 = fterça-feira, 22 de novembro de 2011
  14. 14. 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
  15. 15. Session def contador(): if session.cont: session.cont = session.cont+1 else: session.cont = 1 return dict( contador = session.cont ) session.variavel = "Oinc" session.forget() session.connect(request, response, db, masterapp=None)terça-feira, 22 de novembro de 2011
  16. 16. Response response.body response.cookies response.flash response.headers response.render(view, vars) response.viewterça-feira, 22 de novembro de 2011
  17. 17. 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
  18. 18. 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
  19. 19. 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
  20. 20. Viewterça-feira, 22 de novembro de 2011
  21. 21. Estruturaterça-feira, 22 de novembro de 2011
  22. 22. Template Language Python embutido em HTML Código python entre {{ }} Sem restrições à linguagem Blocos de código finalizados por passterça-feira, 22 de novembro de 2011
  23. 23. Exemplos {{ if request.args(0): response.write(existe) else: response.write(não existe) pass }}terça-feira, 22 de novembro de 2011
  24. 24. Geração da View <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)terça-feira, 22 de novembro de 2011
  25. 25. {{=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 serializarterça-feira, 22 de novembro de 2011
  26. 26. 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
  27. 27. 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
  28. 28. Page Layout layout.html <html><head><title>Page Title</title></head> <body> {{include}} </body> </html> {{extend layout.html}} index.html <h1>Hello World</h1> {{include page.html}}terça-feira, 22 de novembro de 2011
  29. 29. Exemplo controllers/visao.py def lista(): return dict(numeros = range(30)) <ul> views/visao/lista.html {{ for numero in numeros: }} <li> {{=numero }} </li> {{ pass }} </ul>terça-feira, 22 de novembro de 2011
  30. 30. Modelterça-feira, 22 de novembro de 2011
  31. 31. Estruturaterça-feira, 22 de novembro de 2011
  32. 32. Responsabilidades do Model Acessar o Banco Mapear Objetos e Tabelas Gerar SQL dinamicamente Validar campos das tabelas e formuláriosterça-feira, 22 de novembro de 2011
  33. 33. 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
  34. 34. String de Conexão SQLite sqlite://storage.db MySQL mysql://username:password@localhost/ PostgreSQL postgres://username:pass@localhost/test test MSSQL mssql://username:pass@localhost/test Firebird firebird://username:pass@localhost/test Oracle oracle://username/pass@test DB2 db2://username:pass@test Ingres ingres://username:pass@localhost/test Informix informix://username:pass@test Google App gae Engineterça-feira, 22 de novembro de 2011
  35. 35. 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
  36. 36. Tipos de Camposterça-feira, 22 de novembro de 2011
  37. 37. 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
  38. 38. 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
  39. 39. Query Objeto que representa a cláusula “where” do SQL. query = (db.pessoas.nome == Alex)terça-feira, 22 de novembro de 2011
  40. 40. 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
  41. 41. 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 atributosterça-feira, 22 de novembro de 2011
  42. 42. Exemplo de Rows e Row controller def solteiros(): query = (db.pessoas.casado == False) linhas = db(query).select() return dict( linhas = linhas) view <h2>Lista de Solteiros</h2> <ul> {{ for solteiro in linhas: }} solteiro[nome] <li> {{=solteiro.nome }} solteiro(pessoas.nome) {{ pass }} </ul>terça-feira, 22 de novembro de 2011
  43. 43. 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.nometerça-feira, 22 de novembro de 2011
  44. 44. Select: argumentos opcionais orderby groupby rows = db(db.pessoas) .select(orderby=db.pessoas.nome) limitby distinctterça-feira, 22 de novembro de 2011
  45. 45. 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
  46. 46. Campos Computados from 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
  47. 47. 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
  48. 48. Update db.pessoas[ 2 ] db(db.pessoas.id == 2).select().first() obj = db.pessoas(2) obj.update_record(nome=Edna) db(db.pessoas.data_nascimento.year() > 1990). update(db.pessoas.cidade_natal = Teresina)terça-feira, 22 de novembro de 2011
  49. 49. Joins Inner Join db(db.pessoas.id == db.caes.dono).select() Left Outer Join 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
  50. 50. 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
  51. 51. 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 permissionsterça-feira, 22 de novembro de 2011
  52. 52. Authentication Métodos de login: tabela auth_user Google, PAM, LDAP, Facebook, LinkedIn, OpenID, OAuth, etc.terça-feira, 22 de novembro de 2011
  53. 53. 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
  54. 54. Forms FORM SQLFORM SQLFORM.factory CRUDterça-feira, 22 de novembro de 2011
  55. 55. 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
  56. 56. FORM Validaçã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
  57. 57. 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
  58. 58. SQLFORM.factoryterça-feira, 22 de novembro de 2011
  59. 59. CRUD from gluon.tools import Crud crud = Crud(db) 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 dadosterça-feira, 22 de novembro de 2011
  60. 60. Métodos CRUD crud.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
  61. 61. 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
  62. 62. 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 campoterça-feira, 22 de novembro de 2011
  63. 63. 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, CRYPTterça-feira, 22 de novembro de 2011
  64. 64. 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 Callsterça-feira, 22 de novembro de 2011
  65. 65. Generic Views default/contador.xml procura views/default/contador.xml Não encontrando, procura views/default/generic.xml Generics para JSON, PDF, RSS, XMLterça-feira, 22 de novembro de 2011
  66. 66. 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çoterça-feira, 22 de novembro de 2011
  67. 67. Service Decoratorterça-feira, 22 de novembro de 2011
  68. 68. Do que não falamos URL Rewrite Central Authentication Service Roteamento de Erros jQuery e Ajax Tarefas em background Deploy em Servidores de Pyjamas Produção Blocks in Views Escalabidade Caching Google App Engine Exportação e Importação de Componentes e Plugins Dadosterça-feira, 22 de novembro de 2011
  69. 69. 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-169442terça-feira, 22 de novembro de 2011

×