05/02/26, 18:49 Tutorial básico de SQLAlchemy
🇮🇪 Read in English
13 Março 2020 ●
Tutorial básico de SQLAlchemy
Eu trabalhei com o Projeto Jupyter de dezembro/2018 até março/2019 como parte de um estágio no programa Outreachy.
Foi uma experiência maravilhosa e super recomendo! Durante o meu estágio, eu lutei com a biblioteca SQLAlchemy que
o JupyterHub utiliza internamente.
Como estudei essa biblioteca e tive que fazer algumas buscas no Stack Overflow pra entender várias coisas, decidi criar
este post para ajudar a digerir algumas das minhas dúvidas e descobertas.
Todo o código está disponível neste repositório.
Criando e entendendo o Engine (mecanismo)
Para começar a trabalhar com o SQLAlchemy, a primeira coisa que eles ensinam nos tutoriais é que você deve criar um
engine. O engine é como o SQLAlchemy se comunica com o banco de dados. Portanto, ao criar o mecanismo, você deve
adicionar a URL do banco de dados (chamada pela abreviação em inglês db) e é basicamente isso.
from sqlalchemy import create_engine
engine = create_engine('sqlite:///:memory:', echo=True)
Embora você possa acessar o banco de dados por meio de comandos do engine (veremos como), geralmente esse não é o
recomendado. Você pode, mas não deve 🙂
O engine é para ser apenas a ponte de conexão entre o Python e o banco.
Nesse comando, você está apenas dizendo para o SQLAlchemy onde seu banco de dados está localizado. O atributo echo
= True fará com que SQLAlchemy registre no console todos os comandos SQL que você está executando através dos
comandos e os resultados otidos. Esse parâmetro não deve ficar ativado em produção, ok?
[Link] 1/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
Uma vez que seu engine conhece seu banco de dados, é fácil executar comandos usando um método chamado
[Link](...). Veja o exemplo abaixo:
Portanto, você tem uma via de mão dupla: o engine que sabe onde está o seu banco de dados e um método
([Link](...)) para alterar o banco de dados usando o engine:
[Link] 2/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
Engine ou conexão?
Também vi em alguns tutoriais que você tem outra maneira de executar comandos SQL através do engine que é através
de uma connection (conexão). Isso acontece da seguinte forma:
conn = [Link]()
[Link](...)
Isso nos permite criar comandos transientes, o que significa que todos os comandos devem ser executados com êxito no
banco de dados ou todos devem ser revertidos em caso de erro [1]:
trans = [Link]()
[Link]('INSERT INTO "EX1" (name) '
'VALUES ("Hello")')
[Link]()
Então, na verdade, a estrutura de comunicação se parece mais com isso:
No entanto, quando eu continuei investigando as diferenças entre [Link](...) e [Link](...) eu
descobri que elas não são diferentes:
“Usar [Link]() e [Link]() é (quase) a mesma coisa. No primeiro, o objeto connection é criado
implicitamente e, no segundo, nós o instanciamos explicitamente.”
Então, fique à vontade para usar qualquer uma delas, se quiser :)
Até agora, nos conectamos no banco de dados e puder executar comandos através de instruções SQL. No entanto, o que
torna o SQLAlchemy tão atraente é o ORM (Object Relational Mapping), que eu não comentei até agora.
O ORM precisa de uma session (sessão) para fazer um meio de campo entre os objetos que criamos no Python e o engine
que realmente se comunica com o banco de dados. Vamos criar usar uma função chamada sessionmaker pra passar o
engine pra nossa sessão atual e criarmos de fato a sessão:
from [Link] import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
Então, daqui pra frente, nós vamos usar o session para conversar com as tabelas e fazer consultas, mas é o engine que
realmente está implementando coisas no seu banco de dados.
[Link] 3/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
Embora pareça confuso ter três entidades antes mesmo de começar a mexer com tabelas, na maioria das vezes após a
configuração inicial você vai usar a session muito mais do que o engine e a conexão será feita implicitamente por ele.
Criando tabelas
Agora que entendemos a estrutura básica, a primeira coisa a fazer é começar a criar tabelas em nosso banco de dados e
finalmente começar a dar uma olhada no ORM do SQLAlchemy.
Para criar novas tabelas, precisamos criar classes que contêm atributos. Cada classe será uma tabela em nosso banco de
dados e cada atributo será uma coluna na tabela. Para mapear qual tabela no banco de dados será relacionada com cada
classe em nossos arquivos, usaremos um sistema SQLAlchemy chamado Declarative (Declarativo). Para usar isso, a
primeira coisa que devemos fazer é instanciar uma Base:
from [Link] import declarative_base
Base = declarative_base()
Agora vamos criar uma classe User que herda da Base declarativa que acabamos de criar. Criaremos apenas três atributos
para nossa classe: id (que é uma chave primária), um nome e uma senha. Como estamos usando Declarativos, devemos
adicionar pelo menos dois atributos à nossa classe:
1. __tablename__ indica como sua tabela será realmente chamada dentro do banco de dados
2. Ao menos um dos atributos deve ser declarado como uma chave primária [2].
Também é bom adicionar um método opcional chamado __repr__ que será um texto (string) que deve ser retornado
quando tivermos a instância da classe User.
from sqlalchemy import Column, Integer, String
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
password = Column(String)
def __repr__(self):
return f'User {[Link]}'
Agora temos uma classe que indica como nossa tabela deve ser no nosso banco de dados. No entanto, nada mudou até
agora. O banco de dados ainda não conhece essa estrutura. Para realmente criar as tabelas em nosso banco de dados
seguindo a estrutura que definimos na classe User, precisamos usar a Base declarativa que acabamos de criar e
precisamos do engine:
[Link].create_all(engine)
É só nesse momento que o SQLAlchemy realmente vai implementar as mudanças no banco de dados. Como definimos o
parâmetro echo como verdadeiro (True), podemos ver exatamente quais são instruções aplicadas via SQL que o engine
está gerando:
[Link] 4/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
Adicionando novos usuários
Agora que a tabela de fato existe no banco de dados, podemos usar a classe para criar um novo registro no banco.
Podemos usar a classe User para criar um novo usuário e [Link](...) para adicionar a instância ao nosso banco de
dados como uma nova linha.
user = User(name='John Snow', password='johnspassword')
[Link](user)
print([Link]) # None
Anteriormente eu comentei que sempre precisamos de uma chave primária, mas no exemplo acima eu não passei uma
para o modelo. Se eu tentar imprimir o id do usuário que acabei de criar, ele vai retornar None.
Isso ocorre porque o [Link] apenas registra as transações que queremos que sejam feitas, mas na verdade não faz
nenhuma mudança no banco [3].
Conforme explicado neste link, temos duas operações que podem ser realizadas aqui:
[Link]() comunica uma série de operação ao banco de dados (inserir, atualizar, apagar). O banco de dados às
mantém como operações pendentes em uma trasação. As mudanças não são persistidas no dsco ou visíveis em
outras transações até o banco dados receber um COMMIT para a transação atual (que é o que o [Link]()
faz).
ou
[Link]() persiste as mudanças no banco de dados. Esse comando sempre chama [Link]() como
parte dele.
Fazendo buscas
Depois de termos registros no banco de dados, precisamos ter acesso a eles :)
Para isso podemos usar o método query presente na nossa session. O método recebe como parâmetro a classe que
representa a tabela do banco em que queremos fazer a busca pelo nosso registro. Depois usamos o método filter_by
para buscar uma característica em uma das colunas (ou atributos da classe)
query = [Link](User).filter_by(name='John')
[Link] 5/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
Por fim, passamos um método para indicar o que queremos fazer com esta consulta: contar o número de registros
encontrados (.count()), retornar todos os registros encontrados (.all()), retornar apenas o primeiro registro (.first()) e
assim por diante:
[Link]()
Outra maneira de fazer essa busca é usar o método filter, em vez do filter_by, que possui uma sintaxe ligeiramente
diferente:
[Link](User).filter([Link]=='John').first()
Com o método filter, você também pode procurar não por strings exatas mas por partes de strings:
[Link](User).filter([Link]('%John%')).first()
No Jupyterhub, foi adicionado a cada modelo um método de classe que simplifica essa sintaxe bastante complicada.
Nesse caso criamos um método, que é um classmethod, que apenas precisa receber a session e consegue fazer a busca
de maneira mais simples. O método fica escrito dessa forma:
class User(Base):
...
@classmethod
def find_by_name(cls, session, name):
return [Link](cls).filter_by(name=name).all()
E a busca fica mais simples para encontrar usuários com o nome John:
Product.find_by_name(session, 'John')
Adicionando tabelas depois de iniciar o banco com create_all
Um dos problemas que tive enquanto trabalhava com o Projeto Jupyter, é que eu precisava criar uma nova tabela em um
banco de dados e um engine que já estavam criados, ou seja, depois do [Link].create_all(engine).
Então, imagine que agora eu quero uma tabela com Produtos (Product) como a seguinte:
from sqlalchemy import Column, Integer, String
class Product(Base):
__tablename__ = 'products'
id = Column(Integer, primary_key=True)
name = Column(String)
A maneira mais simples que eu encontrei de criar essa nova tabela no banco de dados foi:
Product.__table__.create(engine)
Criando uma relação com chave estrangeira (foreign key)
Imagine que você gostaria de conectar cada produto (product) a um usuário (user) em seu sistema. Portanto, em cada
instância da classe Product, você gostaria de armazenar uma instância da classe User:
[Link] 6/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
Se você estiver criando todas as tabelas agora, uma classe Column como atributo da sua classe Product e indique esse
atributo faz referência à chave estrangeira da classe User e que vai armazenar o atributo id como chave estrangeira:
from sqlalchemy import Column, ForeignKey, Integer, String
from [Link] import relationship
class Product(Base):
__tablename__ = 'product'
id = Column(Integer, primary_key=True)
name = Column(String)
user_id = Column(Integer, ForeignKey('[Link]'))
user = relationship('User')
Agora é preciso ir na classe User e adicionar essa relação com Produto para que seja possível acessar produtos que estão
atrelados a um usuário:
from sqlalchemy import Column, Integer, String
from [Link] import relationship
class User(Base):
__tablename__ = 'user' # if you use base it is obligatory
id = Column(Integer, primary_key=True) # obligatory
name = Column(String)
password = Column(String)
products = relationship(Product, backref="users")
É possível criar as tabelas usando o [Link].create_all(engine) que vimos anteriormente. E agora, você pode criar
um usuário e um produto relacionados entre si da seguinte forma:
user = User(name='John')
product = Product(name='wolf', user=user)
session.add_all([user, product])
[Link]()
E é isso 🙂
[Link] 7/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
❤
Abraço!
Letícia
Comments
ALSO ON [Link]
Seniors are going crazy for these
Free Motion Shoes
The complete step-by- Class Based Views no
I'm not the best step guide to create … Django
5 years ago • 1 comment 4 years ago • 4 comments 5 years ago • 5 comments
All my career I worked in This is the third post on how Este post também poder
places where people were to create your website step ser chamado de o que ve
better than me. Like… way … by step! In this post, we … depois dos tutoriais :)
[Link] 8/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
Sponsored
The best shoes for walking and standing all day
Free Motion Shoes
Novo Ar Portátil lidera vendas, dispensa instalação e gela o quarto em poucos minutos!
Ar Portátil Ultra Potente
Ar Portátil sem dutos no Brasil: tecnologia prática, moderna e eficiente
Ar Portátil Ultra Potente
Shooter Action MMO
Crossout Play Now
Crossout 2.0: Supercharged
Crossout Play Now
This 1-Minute Evening Ritual Can Help Restore Damaged, Fungus-Ridden Nails.
Orivelle
[Link] 9/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
What do you think?
15 Responses
Upvote Funny Love Surprised Angry Sad
4 Comments
1 Login
G Join the discussion…
LOG IN WITH OR SIGN UP WITH DISQUS ?
Name
2 Share Best Newest Oldest
U
Uallas Leles − ⚑
4 years ago
Parabéns, Letícia! Gostei muito do artigo.
0 0 Reply Share ›
J
João Vitor Elias Carvalho − ⚑
4 years ago
Muito bom o artigo! Parabéns!
0 0 Reply Share ›
Ronaldo Silva − ⚑
5 years ago
Muito bom o posto Letícia, parabéns! Gostaria de saber se você vai criar novos posts como esse? Se possível gostaria
também saber como eu conseguiria mostrar dados dos usuários através dos produtos (tipo consultas join). Valeu!
0 0 Reply Share ›
G
Gerson da Silva Correia − ⚑
5 years ago
Bom dia Letícia. Parabéns pelo post, claro e direto, mostrando que são as coisas e como funcionam e não apenas o que elas
fazem.
0 0 Reply Share ›
Subscribe Privacy Do Not Sell My Data
[Link] 10/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
Sponsored
The best shoes for walking and standing all day
Free Motion Shoes
Seniors are going crazy for these comfy, durable, ultra-light shoes
Free Motion Shoes
Novo Ar Portátil lidera vendas, dispensa instalação e gela o quarto em poucos minutos!
Ar Portátil Ultra Potente
Ar Portátil sem dutos no Brasil: tecnologia prática, moderna e eficiente
Ar Portátil Ultra Potente
Shooter Action MMO
Crossout Play Now
Nail Care Expert: If You Have Nail Fungus, Try This Tonight (At Home)
Orivelle
Sobre mim
Uma deva feliz e apaixonada por ciência de dados. Escrevo sobre tecnologia, carreira e vida.
Meu novo livro chegou!
[Link] 11/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
É um livro sobre desenvolvimento de software para quem não é da área e quer saber mais sobre esse mundo, mesmo que
ela não queira se tornar uma desenvolvedora! Já está disponível na pré-venda! :)
[Link] 12/13
05/02/26, 18:49 Tutorial básico de SQLAlchemy
© LETICIA PORTELLA 2020
ALL RIGHTS RESERVED
Tópicos
1. Criando e entendendo o Engine (mecanismo)
2. Engine ou conexão?
3. Criando tabelas
4. Adicionando novos usuários
5. Fazendo buscas
6. Adicionando tabelas depois de iniciar o banco com create_all
7. Criando uma relação com chave estrangeira (foreign key)
Textos em categorias semelhantes
python
tutorial
[Link] 13/13