Começando com SQL Alchemy

Acessando bancos relacionais e criando modelos ORM de forma fácil no Python

· 5 minutos de leitura
sqlalchemy

Diversas aplicaçōes escritas em Python precisam armazenar dados relacionais, usando bancos de dados como PostgreSQL, MySQL, Oracle e outros.

O projeto sqlalchemy visa facilitar a conexão e manipulação de registros.

Veja a seguir como utilizar este projeto.

Instalação

Para realizar a instalação do pacote basta executar:

1
$ pip install sqlalchemy

Após finalizar o download e instalação você pode verificar a instalação pelo python, executando:

1
2
3
4
$ python3
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.3.13'

Conectando e executando queries

Para conectar a um banco de dados suportado pelo sqlalchemy (PostgreSQL, MySQL, SQLite, Oracle ou Microsoft SQL Server) precisamos criar uma instância de Engine, este objeto servirá para criarmos nossas sessões de conexão com o banco.

1
2
from sqlalchemy import create_engine
engine = create_engine("sqlite:///file.db")

No exemplo acima, estamos criando uma instância de Engine com o sqlite, caso você queira conectar com outro banco, veja a documentação (em inglês) para mais detalhes.

Uma vez que temos nossa engine podemos começar a criar nossa sessão.

1
2
3
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()

Finalmente com nossa sessão conseguimos executar comandos SQL, como por exemplo criar um tabela de usuários.

1
2
3
4
session.execute('CREATE TABLE users('
               	'id INT '
               	'name VARCHAR '
               	'email VARCHAR)')

Inserir dados.

1
2
3
4
5
6
session.execute("INSERT INTO "users" (id, name, email) VALUES "
               "(1, 'admin', '[email protected]') ")
session.execute('INSERT INTO "users" (id, name, email) VALUES '
               "(2, 'user', '[email protected]') ")
session.execute('INSERT INTO "users" (id, name, email) VALUES '
               "(3, 'client', '[email protected]') ")

Por fim podemos buscar dados.

1
2
3
4
5
6
result = session.execute('SELECT * FROM users')
for row in result:
    print(row)
#(1, 'admin', '[email protected]')
#(2, 'user', '[email protected]')
#(3, 'client', '[email protected]')

ORM

Além de poder se executar comandos SQL o sqlalchemy também possuí um pacote de ORM (Object-relational mapping ) que basicamente permite mapear as tabelas do banco em classes e objetos de forma fácil e pratica. Para exemplificar vamos continuar a usar nosso exemplo anterior da tabela de usuários, primeiro vamos deletar a tabela.

1
session.execute('DROP TABLE users')

Agora vamos criar uma classe para representar nossos usuários, a documentação do sqlalchemy sugere criar uma classe base para todos os nossos “modelos” usando a função declarative_base() do pacote sqlalchemy.ext conforme o exemplo abaixo.

1
2
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

Com a classe Base conseguimos criar nossos modelos, ou classes que representarão nossas tabelas e dados, veja um exemplo de como criar um modelo.

1
2
3
4
5
6
7
8
from sqlalchemy import Column, Integer, String

class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True)
    name = Column(String(255), nullable=False)
    email = Column(String, nullable=False)

Como pode-se ver no exemplo, quando se utiliza o ORM do sqlalchemy os atributos da classe são inicializados com instâncias de sqlalchemy.Column, no caso estamos criando colunas de “id”, “name” e “email”, cada um destes atributos será uma coluna na tabela gerada, com opções de primary_key para a chave primária da tabela e nullable para indicar que os valores são obrigatórios. Além disso o atributo __tablename__ é obrigatório para indicar o nome da tabela.

Uma vez montado nosso primeiro modelo de usuário, podemos agora gerar toda a estrutura do banco usando um método utilitário da classe Base que criamos.

1
Base.metadata.create_all(engine)

Caso o comando acima seja executado com sucesso é esperado termos agora uma tabela users representado pela nossa classe, com isso podemos da mesma forma que anteriormente adicionar alguns usuários.

1
2
3
4
5
6
7
8
9
admin = User(id=1, name='admin', email='[email protected]')
user = User(id=2, name='user', email='[email protected]')
client = User(id=3, name='client', email='[email protected]')

session.add(admin)
session.add(user)
session.add(client)

session.commit()

Nesse exemplo estamos criando 3 usuários (admin, user e client) e adicionando eles a nossa sessão atual, dessa forma que rastreamos a criação de novos objetos e alterações feitas nestes objetos, após executar o código acima podemos realizar queries para buscar todos os usuários.

1
2
3
4
5
6
users = session.query(User).all()
for user in users:
    print(user.name)
# admin
# user
# client

Perceba a forma como buscamos os usuários com o método query passando como parâmetro a entidade que queremos, no caso User, a forma acima irá buscar todos os usuários sem filtro algum.

Podemos filtrar a busca com o método filter().

1
2
3
4
5
no_admin_users = session.query(User).filter(User.name != 'admin')
for user in no_admin_users:
    print(user.id, user.name)
# 2 user
# 3 client

Podemos utilizar filtros da mesma forma que utilizamos em comandos if, while e outros, podendo retornar todos os resultados com a opção all() ou retornar apenas um registro.

1
admin_user = session.query(User).filter(User.name == 'admin').one()

Para retornar apenas um registro podemos utilizar tanto o método one() quanto o método one_or_none(), a diferença entre os 2 métodos é que o primeiro irá disparar uma exceção caso nenhum registro for encontrado, enquanto o segundo retornará None.

Para saber a lista completo de operadores veja a documentação (em inglês)

Além de inserir e realizar buscas é possível fazer alterações facilmente, basta utilizar a referência ao objeto, alterar os atributos e adicionar a sessão, conforme o exemplo abaixo.

1
2
3
admin_user.email = '[email protected]'
session.add(admin_user)
session.commit()

Dessa forma conseguimos facilmente alterar nosso banco.

Podemos também excluir os registros com o método delete().

1
2
session.delete(admin_user)
session.commit()

Seguindo o mesmo padrão, adicionando os objetos que queremos excluir a sessão e executando o commit() para enviar as alterações.

Conclusão

O sqlalchemy possuí um conjunto de opções que tanto facilitam trabalhar com bancos relacionais como dão flexibilidade de executar comandos SQL ou criar modelos utilizando o pacote ORM.

Você já utilizou esse pacote? Utiliza algum outro meio para se comunicar com seu banco? Possuí alguma dúvida? comente abaixo.