Python Aula 5 SQLAlchemy e CherryPy
Relembrando a aula anterior ....
Acesso a banco de dados Em Python o acesso a banco de dados pode ser feito de 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á vem integrado com Python.
Exemplo SQLite3/DB-API # -*- coding: latin-1 -*- from sqlite3 import dbapi2 as sqlite #Abrindo uma conexão con = sqlite.connect('agenda.db') #Obtendo um cursor cursor = con.cursor() cursor.execute("INSERT INTO agenda(nome, tel) VALUES('Bruno', '123')") #Salvando os dados da transação con.commit()
SQLAlchemy É uma biblioteca que facilita a utilização de bancos de dados por aplicações Python; O SQLAlchemy faz o mapeamento objecto-relacional entre os objetos Python a as tabelas de um banco de dados; SQLAlchemy é suporta qualquer banco de dados que possua módulo DB-API; A instalação do SQLAlchemy pode ser feita de duas formas: Fazendo o download; http://www.sqlalchemy.org/ Utilizando o setuptools.
Setup Tools Objetivo: 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
SQLAlchemy Instalação: Windows: easy_install SQLAlchemy Linux e MacOS: sudo easy_install SQLAlchemy
SQLAlchemy Conceitos 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.
Exemplo Vamos mostrar antes um exemplo para depois apresentar os conceitos em maiores detalhes; Nosso exemplo será uma boa e velha agenda de contatos telefônicos; Faça: Crie um projeto PyDev chamado Agenda; Crie um módulo chamado contato.
Módulo contato from sqlalchemy import * from sqlalchemy.ext.declarative import declarative_base Base = 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
Crie um módulo chamado principal
# -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from contato import Contato, Base import os engine = 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 !'
# -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os engine = 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 !'
# -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = 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 !'
# -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão 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 !'
# -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) Criação do Banco de Dados 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 !'
# -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) Criação do Banco de Dados 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)) 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 !'
# -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) Criação do Banco de Dados 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)) 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 !'
# -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) Criação do Banco de Dados 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)) 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 !'
SQLAlchemy Mapeando 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)
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))
SQLAlchemy Nome do SGBD Obtendo uma engine: engine = create_engine('sqlite:///agenda.db') URL para o banco de dados O nome do SGBD é uma forma do SQLAlchemy localizar o módulo correto, 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 saber como 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 SQL gerado por ela: create_engine('sqlite:///agenda.db', echo=True)
SQLAlchemy Criando 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()
SQLAlchemy Gravando 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ções realizar o commit, pois, caso contrário, os dados não serão persistidos; Caso algum erro ocorra, você deve chamar o rollback, para deixar o estado do banco de dados igual ao do último commit realizado.
SQLAlchemy - Consultas Pela 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.
SQLAlchemy - Filtros Filtrando 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’)
SQLAlchemy - Filtros Filtrando 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’)
SQLAlchemy - Filtros Filtrando 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’)
SQLAlchemy Para 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 o método delete na sessão e fazer commit: contato = session.query(Contato).get(5) session.delete(contato) session.commit()
Desafio Exiba o ID do contato assim que ele for criado: Foi criado um contato com o id X; Adicione na agenda a possibilidade de procurar um contato 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.
Relacionamentos É possível definir relacionamentos entre as classes mapeadas; 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.
from sqlalchemy import * from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nome class 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
from sqlalchemy import * from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nome class 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
from sqlalchemy import * from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nome class 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
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.
Trabalhando com relacionamentos 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()
Desafio Façam com que um Contato possa ter mais do que um número de telefone; Permitam que na adição o usuário possa digitar quantos 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.
CherryPy Pequeno framework HTTP escrito em Python; Com ele é possível desenvolver aplicações web completas; Porém seu foco é no desenvolvimento rápido de pequenos aplicativos web; Site: http://www.cherrypy.org
CherryPy Instalaçã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
Hello World import cherrypy class HelloWorld: @cherrypy.expose def index(self): return "Hello world!" cherrypy.quickstart(HelloWorld())
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())
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())
CherryPy Conceitos 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
Exemplo import cherrypy class HelloWorld: @cherrypy.expose def index(self): return "INDEX" @cherrypy.expose def cadastro(self): return "CADASTRO" cherrypy.quickstart(HelloWorld())
Arquivo de configuração Você pode especificar os parâmetros básicos da sua aplicação em um arquivo de configuração simples; Este arquivo pode estar localizado em qualquer lugar do seu computador (de preferência no mesmo diretório do seu projeto) e deverá ser informado na função quickstart; 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"
Arquivo de configuração Você pode especificar os parâmetros básicos da sua aplicação em um arquivo de configuração simples; Este arquivo pode estar localizado em qualquer lugar do seu computador (de preferência no mesmo diretório do seu projeto) e deverá ser informado na função quickstart; Este arquivo pode ter qualquer nome 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"
Exemplo Crie 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;
Arquivo server.cfg
Arquivo server.cfg Caminho completo do seu projeto
Módulo testeweb
Arquivo teste.html
Executando Execute o módulo testeweb; Em um navegador abra os endereços: http://localhost:8080 http://localhost:8080/static/teste.html
Trabalhando com formuários Formulários são uma das formas em HTML de passar parâmetros dos clientes para o servidor; Vamos mudar o arquivo teste.html e o módulo testeweb para exemplificar o uso de formulários.
Arquivo teste.html
Módulo testeweb
Executando Execute o módulo testeweb; Em um navegador abra os endereços: http://localhost:8080/static/teste.html Preencha e submeta o formulário.
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.
Exemplo from string import Template t = Template('Login: $login - Senha: $senha') print t.substitute(login='system', senha='123')
Desafio Crie um aplicativo web com o CherryPy que possua duas 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 pode parecer !

Python 05

  • 1.
  • 2.
    Relembrando a aula anterior ....
  • 3.
    Acesso a bancode dados Em Python o acesso a banco de dados pode ser feito de 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á vem integrado com Python.
  • 4.
    Exemplo SQLite3/DB-API # -*-coding: latin-1 -*- from sqlite3 import dbapi2 as sqlite #Abrindo uma conexão con = sqlite.connect('agenda.db') #Obtendo um cursor cursor = con.cursor() cursor.execute("INSERT INTO agenda(nome, tel) VALUES('Bruno', '123')") #Salvando os dados da transação con.commit()
  • 5.
    SQLAlchemy É uma bibliotecaque facilita a utilização de bancos de dados por aplicações Python; O SQLAlchemy faz o mapeamento objecto-relacional entre os objetos Python a as tabelas de um banco de dados; SQLAlchemy é suporta qualquer banco de dados que possua módulo DB-API; A instalação do SQLAlchemy pode ser feita de duas formas: Fazendo o download; http://www.sqlalchemy.org/ Utilizando o setuptools.
  • 6.
    Setup Tools Objetivo: Instalaçãofá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.
    SQLAlchemy Instalação: Windows: easy_install SQLAlchemy Linux e MacOS: sudo easy_install SQLAlchemy
  • 8.
    SQLAlchemy Conceitos 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.
    Exemplo Vamos mostrar antesum exemplo para depois apresentar os conceitos em maiores detalhes; Nosso exemplo será uma boa e velha agenda de contatos telefônicos; Faça: Crie um projeto PyDev chamado Agenda; Crie um módulo chamado contato.
  • 10.
    Módulo contato from sqlalchemyimport * from sqlalchemy.ext.declarative import declarative_base Base = 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.
    Crie um módulochamado principal
  • 12.
    # -*- coding:latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from contato import Contato, Base import os engine = 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.
    # -*- coding:latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os engine = 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.
    # -*- coding:latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = 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.
    # -*- coding:latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão 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 !'
  • 16.
    # -*- coding:latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) Criação do Banco de Dados 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 !'
  • 17.
    # -*- coding:latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) Criação do Banco de Dados 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)) 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.
    # -*- coding:latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) Criação do Banco de Dados 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)) 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.
    # -*- coding:latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Imports from contato import Contato, Base import os Criação da Engine engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() Criação da Sessão if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) Criação do Banco de Dados 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)) 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.
    SQLAlchemy Mapeando uma classeem 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.
    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.
    SQLAlchemy Nome do SGBD Obtendo uma engine: engine = create_engine('sqlite:///agenda.db') URL para o banco de dados O nome do SGBD é uma forma do SQLAlchemy localizar o módulo correto, 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 saber como 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 SQL gerado por ela: create_engine('sqlite:///agenda.db', echo=True)
  • 23.
    SQLAlchemy Criando automaticamente astabelas: 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.
    SQLAlchemy Gravando objetos nobanco 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ções realizar o commit, pois, caso contrário, os dados não serão persistidos; Caso algum erro ocorra, você deve chamar o rollback, para deixar o estado do banco de dados igual ao do último commit realizado.
  • 25.
    SQLAlchemy - Consultas Pelachave 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.
    SQLAlchemy - Filtros Filtrandopor 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.
    SQLAlchemy - Filtros Filtrandopor 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.
    SQLAlchemy - Filtros Filtrandopor 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.
    SQLAlchemy Para alterar umregistro é 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 o método delete na sessão e fazer commit: contato = session.query(Contato).get(5) session.delete(contato) session.commit()
  • 30.
    Desafio Exiba o IDdo contato assim que ele for criado: Foi criado um contato com o id X; Adicione na agenda a possibilidade de procurar um contato 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.
    Relacionamentos É possível definirrelacionamentos entre as classes mapeadas; 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.
    from sqlalchemy import* from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nome class 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.
    from sqlalchemy import* from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nome class 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.
    from sqlalchemy import* from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Montadora(Base): __tablename__ = "montadora" id = Column(Integer, primary_key=True) nome = Column(String) def __init__(self, nome): self.nome = nome class 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.
    Função relationship Afunçã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.
    Trabalhando com relacionamentos 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.
    Desafio Façam com queum Contato possa ter mais do que um número de telefone; Permitam que na adição o usuário possa digitar quantos 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.
    CherryPy Pequeno framework HTTPescrito em Python; Com ele é possível desenvolver aplicações web completas; Porém seu foco é no desenvolvimento rápido de pequenos aplicativos web; Site: http://www.cherrypy.org
  • 39.
    CherryPy Instalação: Façado 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.
    Hello World import cherrypy class HelloWorld: @cherrypy.expose def index(self): return "Hello world!" cherrypy.quickstart(HelloWorld())
  • 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.
    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.
    CherryPy Conceitos 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.
    Exemplo import cherrypy class HelloWorld: @cherrypy.expose def index(self): return "INDEX" @cherrypy.expose def cadastro(self): return "CADASTRO" cherrypy.quickstart(HelloWorld())
  • 45.
    Arquivo de configuração Vocêpode especificar os parâmetros básicos da sua aplicação em um arquivo de configuração simples; Este arquivo pode estar localizado em qualquer lugar do seu computador (de preferência no mesmo diretório do seu projeto) e deverá ser informado na função quickstart; 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.
    Arquivo de configuração Vocêpode especificar os parâmetros básicos da sua aplicação em um arquivo de configuração simples; Este arquivo pode estar localizado em qualquer lugar do seu computador (de preferência no mesmo diretório do seu projeto) e deverá ser informado na função quickstart; Este arquivo pode ter qualquer nome 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"
  • 47.
    Exemplo Crie 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.
  • 49.
    Arquivo server.cfg Caminho completo do seu projeto
  • 50.
  • 51.
  • 52.
    Executando Execute o módulotesteweb; Em um navegador abra os endereços: http://localhost:8080 http://localhost:8080/static/teste.html
  • 53.
    Trabalhando com formuários Formuláriossão uma das formas em HTML de passar parâmetros dos clientes para o servidor; Vamos mudar o arquivo teste.html e o módulo testeweb para exemplificar o uso de formulários.
  • 54.
  • 55.
  • 56.
    Executando Execute o módulotesteweb; Em um navegador abra os endereços: http://localhost:8080/static/teste.html Preencha e submeta o formulário.
  • 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.
    Exemplo fromstring import Template t = Template('Login: $login - Senha: $senha') print t.substitute(login='system', senha='123')
  • 59.
    Desafio Crie um aplicativoweb com o CherryPy que possua duas 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 pode parecer !