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 !