Python 05

963 views
894 views

Published on

Mais uma aula do curso de Python: SQL Alchemy e Cherrypy

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
963
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
57
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Python 05

    1. 1. PythonAula 5SQLAlchemy eCherryPy
    2. 2. Relembrando a aula anterior ....
    3. 3. Acesso a banco de dadosEm Python o acesso a banco de dados pode ser feitode várias maneiras. As principais são: A partir de módulos compatíveis com a especificação DB-API; Utilizando bibliotecas que fazem mapeamento objeto-relacional (ex: SQLAlchemy);Nos nossos exemplos utilizamos o SQLite, pois já vemintegrado com Python.
    4. 4. Exemplo SQLite3/DB-API# -*- coding: latin-1 -*-from sqlite3 import dbapi2 as sqlite#Abrindo uma conexãocon = sqlite.connect(agenda.db)#Obtendo um cursorcursor = con.cursor()cursor.execute("INSERT INTO agenda(nome, tel) VALUES(Bruno, 123)")#Salvando os dados da transaçãocon.commit()
    5. 5. SQLAlchemyÉ uma biblioteca que facilita a utilização de bancos dedados por aplicações Python;O SQLAlchemy faz o mapeamento objecto-relacional entreos objetos Python a as tabelas de um banco de dados;SQLAlchemy é suporta qualquer banco de dados quepossua módulo DB-API;A instalação do SQLAlchemy pode ser feita de duasformas: Fazendo o download; http://www.sqlalchemy.org/ Utilizando o setuptools.
    6. 6. Setup ToolsObjetivo: Instalação fácil de pacotes Python;Link para download: http://pypi.python.org/pypi/setuptools/Instalação: Windows: Execute o arquivo setuptools-0.6c11.win32- py2.6.exe; Linux e MacOS: sudo sh setuptools-0.6c11-py2.6.egg
    7. 7. SQLAlchemyInstalação: Windows: easy_install SQLAlchemy Linux e MacOS: sudo easy_install SQLAlchemy
    8. 8. SQLAlchemyConceitos básicos: Você deve criar classes para mapear as tabelas do banco de dados; As operações serão feitas apenas sobre as classes, não necessitando trabalhar com SQL; A conexão ao banco de dados é feita através de uma engine; As operações com o banco de dados são feitas em uma sessão; Uma sessão define uma transação.
    9. 9. ExemploVamos mostrar antes um exemplo para depoisapresentar os conceitos em maiores detalhes;Nosso exemplo será uma boa e velha agenda decontatos telefônicos;Faça: Crie um projeto PyDev chamado Agenda; Crie um módulo chamado contato.
    10. 10. Módulo contatofrom sqlalchemy import *from sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()class Contato(Base): __tablename__ = agenda id = Column(Integer, primary_key=True) nome = Column(String(30)) tel = Column(String(20)) def __init__(self, nome, tel): self.nome = nome self.tel = tel
    11. 11. Crie um módulo chamadoprincipal
    12. 12. # -*- coding: latin-1 -*-from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmakerfrom contato import Contato, Baseimport osengine = create_engine(sqlite:///agenda.db)Session = sessionmaker(bind=engine)session = Session()if not os.path.exists(agenda.db): Base.metadata.create_all(engine)while True: opcao = raw_input(Qual a sua opção (a)dicionar, (l)istar ou (s)air: ) if opcao == a: nome = raw_input(Digite o nome: ) tel = raw_input(Digite o telefone: ) session.add(Contato(nome, tel)) session.commit() elif opcao == l: for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == s: break else: print Digite uma opção válida !
    13. 13. # -*- coding: latin-1 -*-from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmaker Importsfrom contato import Contato, Baseimport osengine = create_engine(sqlite:///agenda.db)Session = sessionmaker(bind=engine)session = Session()if not os.path.exists(agenda.db): Base.metadata.create_all(engine)while True: opcao = raw_input(Qual a sua opção (a)dicionar, (l)istar ou (s)air: ) if opcao == a: nome = raw_input(Digite o nome: ) tel = raw_input(Digite o telefone: ) session.add(Contato(nome, tel)) session.commit() elif opcao == l: for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == s: break else: print Digite uma opção válida !
    14. 14. # -*- coding: latin-1 -*-from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmaker Importsfrom contato import Contato, Baseimport os Criação da Engineengine = create_engine(sqlite:///agenda.db)Session = sessionmaker(bind=engine)session = Session()if not os.path.exists(agenda.db): Base.metadata.create_all(engine)while True: opcao = raw_input(Qual a sua opção (a)dicionar, (l)istar ou (s)air: ) if opcao == a: nome = raw_input(Digite o nome: ) tel = raw_input(Digite o telefone: ) session.add(Contato(nome, tel)) session.commit() elif opcao == l: for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == s: break else: print Digite uma opção válida !
    15. 15. # -*- coding: latin-1 -*-from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmaker Importsfrom contato import Contato, Baseimport os Criação da Engineengine = create_engine(sqlite:///agenda.db)Session = sessionmaker(bind=engine)session = Session() Criação da Sessãoif not os.path.exists(agenda.db): Base.metadata.create_all(engine)while True: opcao = raw_input(Qual a sua opção (a)dicionar, (l)istar ou (s)air: ) if opcao == a: nome = raw_input(Digite o nome: ) tel = raw_input(Digite o telefone: ) session.add(Contato(nome, tel)) session.commit() elif opcao == l: for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == s: break else: print Digite uma opção válida !
    16. 16. # -*- coding: latin-1 -*-from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmaker Importsfrom contato import Contato, Baseimport os Criação da Engineengine = create_engine(sqlite:///agenda.db)Session = sessionmaker(bind=engine)session = Session() Criação da Sessãoif not os.path.exists(agenda.db): Base.metadata.create_all(engine) Criação do Banco de Dadoswhile True: opcao = raw_input(Qual a sua opção (a)dicionar, (l)istar ou (s)air: ) if opcao == a: nome = raw_input(Digite o nome: ) tel = raw_input(Digite o telefone: ) session.add(Contato(nome, tel)) session.commit() elif opcao == l: for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == s: break else: print Digite uma opção válida !
    17. 17. # -*- coding: latin-1 -*-from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmaker Importsfrom contato import Contato, Baseimport os Criação da Engineengine = create_engine(sqlite:///agenda.db)Session = sessionmaker(bind=engine)session = Session() Criação da Sessãoif not os.path.exists(agenda.db): Base.metadata.create_all(engine) Criação do Banco de Dadoswhile True: opcao = raw_input(Qual a sua opção (a)dicionar, (l)istar ou (s)air: ) if opcao == a: nome = raw_input(Digite o nome: ) tel = raw_input(Digite o telefone: ) session.add(Contato(nome, tel)) Adicionando um objeto ao banco session.commit() elif opcao == l: for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == s: break else: print Digite uma opção válida !
    18. 18. # -*- coding: latin-1 -*-from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmaker Importsfrom contato import Contato, Baseimport os Criação da Engineengine = create_engine(sqlite:///agenda.db)Session = sessionmaker(bind=engine)session = Session() Criação da Sessãoif not os.path.exists(agenda.db): Base.metadata.create_all(engine) Criação do Banco de Dadoswhile True: opcao = raw_input(Qual a sua opção (a)dicionar, (l)istar ou (s)air: ) if opcao == a: nome = raw_input(Digite o nome: ) tel = raw_input(Digite o telefone: ) session.add(Contato(nome, tel)) Adicionando um objeto ao banco session.commit() elif opcao == l: Listando todos os contatos for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == s: break else: print Digite uma opção válida !
    19. 19. # -*- coding: latin-1 -*-from sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmaker Importsfrom contato import Contato, Baseimport os Criação da Engineengine = create_engine(sqlite:///agenda.db)Session = sessionmaker(bind=engine)session = Session() Criação da Sessãoif not os.path.exists(agenda.db): Base.metadata.create_all(engine) Criação do Banco de Dadoswhile True: opcao = raw_input(Qual a sua opção (a)dicionar, (l)istar ou (s)air: ) if opcao == a: nome = raw_input(Digite o nome: ) tel = raw_input(Digite o telefone: ) session.add(Contato(nome, tel)) Adicionando um objeto ao banco session.commit() elif opcao == l: Listando todos os contatos for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == s: Ordenados pelo atributo nome break else: print Digite uma opção válida !
    20. 20. SQLAlchemyMapeando uma classe em uma tabela: É necessário criar uma classe para cada tabela que se queira mapear; As próprias classes podem ser utilizadas para criar as tabelas, caso elas não existam;Forma geral: from sqlalchemy import * from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Contato(Base): __tablename__ = agenda Atributo obrigatório id = Column(Integer, primary_key=True) nome = Column(String) tel = Column(String)
    21. 21. SQLAlchemy Com exceção do Oracle e do Firebird, todos os outros bancos de dados têm suporte a colunas com auto incremento (para as chaves primárias); Para o Oracle e Firebird é necessário especificar uma seqüência:class Contato(Base): __tablename__ = agenda id = Column(Integer, Sequence(contato_seq), primary_key=True) nome = Column(String(30)) tel = Column(String(20))
    22. 22. SQLAlchemy Nome do SGBDObtendo uma engine: engine = create_engine(sqlite:///agenda.db) URL para o banco de dadosO nome do SGBD é uma forma do SQLAlchemy localizar o módulocorreto, alguns exemplos de nomes são: sqlite, mysql, postgresql, mssql,oracle, ...A URL para o banco de dados é dependente do módulo que se estáutilizando, por isso, deve-se ler a documentação do módulo para sabercomo construir a URL;Exemplos: mssql://user:passwd@mydsn, oracle://scott:tiger@127.0.0.1:1521/sidname, mysql://scott:tiger@localhost/foo, ...Você pode, na criação, pedir que a engine mostre todos o código SQLgerado por ela: create_engine(sqlite:///agenda.db, echo=True)
    23. 23. SQLAlchemyCriando automaticamente as tabelas: Para isto, após a definição do mapeamento, utiliza- se o atributo metadata da classe Base: Base.metadata.create_all(engine)Obtendo uma sessão: As sessões estão sempre associadas a uma engine: Session = sessionmaker(bind=engine) session = Session()
    24. 24. SQLAlchemyGravando objetos no banco de dados: session.add(objeto) session.commit( )Você pode adicionar uma lista de objetos de uma vez só: session.add_all([objeto1, objeto2, objeto3])Atenção: Lembre-se sempre de após um bloco de atualizaçõesrealizar o commit, pois, caso contrário, os dados não serãopersistidos;Caso algum erro ocorra, você deve chamar o rollback, paradeixar o estado do banco de dados igual ao do último commitrealizado.
    25. 25. SQLAlchemy - ConsultasPela chave primária: bruno = session.query(Contato).get(5)Retornando todos os registros: contatos = session.query(Contato).all( )Ordenando os resultados: contatos = session.query(Contato).order_by(Contato.nome).all( )Restringindo os resultados: Você pode usar o método all, para obter todos os resultados ou first para obter apenas o primeiro.
    26. 26. SQLAlchemy - FiltrosFiltrando por um campo: pedro = session.query(Contato).filter(Contato.nome == ”Pedro”).first( )Outras operações com filtros: Pessoa.idade >= 18 Contato.nome != ”Bruno” Contato.nome == None Contato.nome != None Contato.nome.like(”Maria%”) Endereco.estado.in_[”PB”, “PE”, “RN”] ~Endereco.estado.in_[”PB”, “PE”, “RN”] and_(Contato.nome == “Bruno”, Contato.telefone == “333”) or_(Endereco.estado == ‘PB’, Endereco.cidade == ‘Campina Grande’)
    27. 27. SQLAlchemy - FiltrosFiltrando por um campo: pedro = session.query(Contato).filter(Contato.nome == ”Pedro”).first( )Outras operações com filtros: Você pode utilizar qualquer operador lógico: Pessoa.idade >= 18 >, <, >=, <=, ==, != Contato.nome != ”Bruno” Contato.nome == None Contato.nome != None Contato.nome.like(”Maria%”) Endereco.estado.in_[”PB”, “PE”, “RN”] ~Endereco.estado.in_[”PB”, “PE”, “RN”] and_(Contato.nome == “Bruno”, Contato.telefone == “333”) or_(Endereco.estado == ‘PB’, Endereco.cidade == ‘Campina Grande’)
    28. 28. SQLAlchemy - FiltrosFiltrando por um campo: pedro = session.query(Contato).filter(Contato.nome == ”Pedro”).first( )Outras operações com filtros: Você pode utilizar qualquer operador lógico: Pessoa.idade >= 18 >, <, >=, <=, ==, != Contato.nome != ”Bruno” Contato.nome == None Contato.nome != None Contato.nome.like(”Maria%”) Você pode ter 2 ou mais Endereco.estado.in_[”PB”, “PE”, “RN”] argumentos no and e no or ~Endereco.estado.in_[”PB”, “PE”, “RN”] and_(Contato.nome == “Bruno”, Contato.telefone == “333”) or_(Endereco.estado == ‘PB’, Endereco.cidade == ‘Campina Grande’)
    29. 29. SQLAlchemyPara alterar um registro é preciso: obtê-lo na sessão,modificar seus valores e fazer commit da sessão: contato = session.query(Contato).get(5) contato.tel = 8888-8888 session.commit()Para remover um registro é preciso: obtê-lo, chamar ométodo delete na sessão e fazer commit: contato = session.query(Contato).get(5) session.delete(contato) session.commit()
    30. 30. DesafioExiba o ID do contato assim que ele for criado: Foi criado um contato com o id X;Adicione na agenda a possibilidade de procurar umcontato pelo nome;Adicione as funcionalidades de atualizar e remover: Dica: Peça pro usuário digitar o id do contato que ele quer atualizar/remover, procure o contato por este id e realize a operação desejada.
    31. 31. RelacionamentosÉ possível definir relacionamentos entre as classesmapeadas;Por exemplo: Contatos podem ter um ou mais números de telefone; Empresas podem ter um ou mais funcionários; Professores lecionam uma ou mais disciplina que, por sua vez, possui um ou mais alunos matriculados.
    32. 32. from sqlalchemy import *from sqlalchemy.orm import relationship, backreffrom sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nomeclass Carro(Base): __tablename__ = "carro" id = Column(Integer, primary_key=True) modelo = Column(String) ano = Column(Integer) montadora_id = Column(Integer, ForeignKey("montadora.id")) montadora = relationship(Montadora, backref=backref(carros, order_by=id)) def __init__(self, modelo, ano, montadora): self.modelo = modelo self.ano = ano self.montadora = montadora
    33. 33. from sqlalchemy import *from sqlalchemy.orm import relationship, backreffrom sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nomeclass Carro(Base): __tablename__ = "carro" Definição da id = Column(Integer, primary_key=True) chave estrangeira modelo = Column(String) ano = Column(Integer) montadora_id = Column(Integer, ForeignKey("montadora.id")) montadora = relationship(Montadora, backref=backref(carros, order_by=id)) def __init__(self, modelo, ano, montadora): self.modelo = modelo self.ano = ano self.montadora = montadora
    34. 34. from sqlalchemy import *from sqlalchemy.orm import relationship, backreffrom sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nomeclass Carro(Base): __tablename__ = "carro" Definição da id = Column(Integer, primary_key=True) chave estrangeira modelo = Column(String) ano = Column(Integer) montadora_id = Column(Integer, ForeignKey("montadora.id")) montadora = relationship(Montadora, backref=backref(carros, order_by=id)) def __init__(self, modelo, ano, montadora): Definição do relacionamento self.modelo = modelo self.ano = ano self.montadora = montadora
    35. 35. Função relationship A função relationship deve estar no lado MUITOS da relação; Forma geral: relationship(ClasseDestino, backref) Backref - Definição do relacionamento na classe de destino: backref(‘atributo a ser criado’, order_by=campo) A função backref irá criar um atributo com o nome especificado na classe de destino.
    36. 36. Trabalhando comrelacionamentos Adição: ford = Montadora(Ford) fiesta = Carro(Fiesta, 2010, ford) session.add(fiesta) session.commit() Navegação:ford = session.query(Montadora).filter(Montadora.nome == Ford).first()for carro in ford.carros: print carro.modelo Remoção: del ford.carros[0] session.commit()
    37. 37. DesafioFaçam com que um Contato possa ter mais do queum número de telefone;Permitam que na adição o usuário possa digitarquantos números quiser. Faça uma pergunta: Adicionar mais um número (s)im ou (n)ão ?Na listagem dos contatos, exibir, para cada contato,todos os seus números.
    38. 38. CherryPyPequeno framework HTTP escrito em Python;Com ele é possível desenvolver aplicações webcompletas;Porém seu foco é no desenvolvimento rápido depequenos aplicativos web;Site: http://www.cherrypy.org
    39. 39. CherryPyInstalação: Faça do download no site da última versão estável (3.1.2); No caso do Windows é só executar o instalador; Nos SOs baseados em Unix você deve descompactar o arquivo (.tar.gz) e executar: sudo python setup.py install
    40. 40. Hello World import cherrypy class HelloWorld: @cherrypy.expose def index(self): return "Hello world!" cherrypy.quickstart(HelloWorld())
    41. 41. Hello World Abra o endereço http://localhost:8080 no seu navegador import cherrypy class HelloWorld: @cherrypy.expose def index(self): return "Hello world!" cherrypy.quickstart(HelloWorld())
    42. 42. Hello World Abra o endereço http://localhost:8080 no seu navegador import cherrypy class HelloWorld: Decorador: diz que o método @cherrypy.expose pode exposto pelo CherryPy def index(self): return "Hello world!" cherrypy.quickstart(HelloWorld())
    43. 43. CherryPyConceitos básicos: Sites são definidos por classes; O método index do objeto principal publicado será mapeado para o endereço raiz (/); Os demais métodos serão mapeados como urls: /hello
    44. 44. Exemplo import cherrypy class HelloWorld: @cherrypy.expose def index(self): return "INDEX" @cherrypy.expose def cadastro(self): return "CADASTRO" cherrypy.quickstart(HelloWorld())
    45. 45. Arquivo de configuraçãoVocê pode especificar os parâmetros básicos da suaaplicação em um arquivo de configuração simples;Este arquivo pode estar localizado em qualquer lugardo seu computador (de preferência no mesmo diretóriodo seu projeto) e deverá ser informado na funçãoquickstart;Formato do arquivo (server.cfg): [global] server.socket_port = 8000 server.thread_pool = 10 tools.sessions.on = True tools.staticdir.root = "/home/site" [/static] tools.staticdir.on = True tools.staticdir.dir = "static"
    46. 46. Arquivo de configuraçãoVocê pode especificar os parâmetros básicos da suaaplicação em um arquivo de configuração simples;Este arquivo pode estar localizado em qualquer lugardo seu computador (de preferência no mesmo diretóriodo seu projeto) e deverá ser informado na funçãoquickstart; Este arquivo pode ter qualquer nomeFormato do arquivo (server.cfg): [global] server.socket_port = 8000 server.thread_pool = 10 tools.sessions.on = True tools.staticdir.root = "/home/site" [/static] tools.staticdir.on = True tools.staticdir.dir = "static"
    47. 47. ExemploCrie um projeto (TesteWeb);Na pasta src crie um arquivo chamado server.cfg;Crie uma pasta chamada static;Crie um módulo chamado testeweb;Na pasta static crie um arquivo chamado teste.html;
    48. 48. Arquivo server.cfg
    49. 49. Arquivo server.cfg Caminho completo do seu projeto
    50. 50. Módulo testeweb
    51. 51. Arquivo teste.html
    52. 52. ExecutandoExecute o módulo testeweb;Em um navegador abra os endereços: http://localhost:8080 http://localhost:8080/static/teste.html
    53. 53. Trabalhando com formuáriosFormulários são uma das formas em HTML de passarparâmetros dos clientes para o servidor;Vamos mudar o arquivo teste.html e o módulotesteweb para exemplificar o uso de formulários.
    54. 54. Arquivo teste.html
    55. 55. Módulo testeweb
    56. 56. ExecutandoExecute o módulo testeweb;Em um navegador abra os endereços: http://localhost:8080/static/teste.htmlPreencha e submeta o formulário.
    57. 57. Tópico interessante Templates Você pode usá-los para construir páginas dinâmicas; Como funcionam: Você cria um texto com variáveis: $nome_variavel; Depois você pode substituir estas variáveis por valores.
    58. 58. Exemplo from string import Template t = Template(Login: $login - Senha: $senha) print t.substitute(login=system, senha=123)
    59. 59. DesafioCrie um aplicativo web com o CherryPy que possuaduas funções: index: Exibe todos os contatos cadastrados; cadastra: Adiciona mais um contato ao banco;Utilize os exemplos do SQLAlchemy, CherryPy e doálbum de fotografias para se inspirar;Fazer este desafio é muito mais simples do que podeparecer !

    ×