Django
Django
docker run -d \
-p 9000:9000 \
-p 8000:8000 \
--name portainer \
--restart=always \
-v /var/run/[Link]:/var/run/[Link] \
-v portainer_data:/data \
portainer/portainer-ce
Relacionamento no Django
No Django, quando você quer relacionar duas tabelas, você usa ForeignKey,
OneToOneField ou ManyToManyField.
class Autor([Link]):
nome = [Link](max_length=100)
class Livro([Link]):
titulo = [Link](max_length=100)
autor = [Link](Autor, on_delete=[Link])
O que acontece:
Se você usar SQLite, PostgreSQL ou MySQL, a tabela Livro vai ter algo assim:
id titulo autor_id
1 “Python” 1
2 “Django DRF” 1
Tabela Autor:
id nome
1 João Silva
2 Maria
No serializer:
class LivroSerializer([Link]):
class Meta:
model = Livro
fields = '__all__'
{
"id": 1,
"titulo": "Python",
"autor": 1
}
class AutorSerializer([Link]):
class Meta:
model = Autor
fields = '__all__'
class LivroSerializer([Link]):
autor = AutorSerializer() # mostra os dados do autor
class Meta:
model = Livro
fields = '__all__'
Resultado:
{
"id": 1,
"titulo": "Python",
"autor": {
"id": 1,
"nome": "João Silva"
}
}
🔹 Resumo do relacionamento
🔹 O que é on_delete?
Quando você cria um campo ForeignKey em um modelo, ele cria um relacionamento
entre tabelas.
🔹 Sintaxe básica
from [Link] import models
class Autor([Link]):
nome = [Link](max_length=100)
class Livro([Link]):
titulo = [Link](max_length=100)
autor = [Link](Autor, on_delete=[Link])
🔹 Tipos de on_delete
Opção O que faz
👉 Quando um autor é apagado, o livro continua, mas o campo autor fica vazio (NULL).
🔹 Exemplo com PROTECT
class Livro([Link]):
titulo = [Link](max_length=100)
autor = [Link](Autor, on_delete=[Link])
👉 Tenta apagar o autor e Django vai impedir se existir algum livro relacionado.
💡 Dica profissional:
Se tu estiveres criando uma API REST com DRF, sempre planeja relacionamentos
com on_delete antes de popular o banco, especialmente se tiver muitos ForeignKey
para outras tabelas.
Ah! Agora a tua dúvida é como o Django cria o relacionamento entre tabelas usando
ForeignKey (e, portanto, on_delete). Vou explicar detalhadamente. 👇
🔹 Relacionamento no Django
No Django, quando você quer relacionar duas tabelas, você usa ForeignKey,
OneToOneField ou ManyToManyField.
class Autor([Link]):
nome = [Link](max_length=100)
class Livro([Link]):
titulo = [Link](max_length=100)
autor = [Link](Autor, on_delete=[Link])
O que acontece:
Se você usar SQLite, PostgreSQL ou MySQL, a tabela Livro vai ter algo assim:
id titulo autor_id
1 “Python” 1
2 “Django DRF” 1
Tabela Autor:
id nome
1 João Silva
2 Maria
No serializer:
class LivroSerializer([Link]):
class Meta:
model = Livro
fields = '__all__'
{
"id": 1,
"titulo": "Python",
"autor": 1
}
class AutorSerializer([Link]):
class Meta:
model = Autor
fields = '__all__'
class LivroSerializer([Link]):
autor = AutorSerializer() # mostra os dados do autor
class Meta:
model = Livro
fields = '__all__'
Resultado:
{
"id": 1,
"titulo": "Python",
"autor": {
"id": 1,
"nome": "João Silva"
}
}
🔹 Resumo do relacionamento
Se quiser, posso fazer um diagrama visual mostrando Autor ↔ Livro e como a API
REST se comporta quando deletamos um autor 🔥
class Autor([Link]):
nome = [Link](max_length=100)
class Livro([Link]):
titulo = [Link](max_length=100)
autor = [Link](Autor, on_delete=[Link])
Explicação:
Quando o autor é deletado, o livro continua existindo, mas o campo autor fica NULL.
class Perfil([Link]):
usuario = [Link]('[Link]',
on_delete=[Link])
telefone = [Link](max_length=20)
class Aluno([Link]):
nome = [Link](max_length=100)
class Curso([Link]):
nome = [Link](max_length=100)
alunos = [Link](Aluno)
Um aluno pode estar em vários cursos.
Um curso pode ter vários alunos.
Django cria uma tabela intermediária automaticamente para gerenciar esse
relacionamento.
class LivroSerializer([Link]):
autor = AutorSerializer() # mostra detalhes do autor
class Meta:
model = Livro
fields = '__all__'
Resultado JSON:
{
"id": 1,
"titulo": "Python Avançado",
"autor": {
"id": 1,
"nome": "João Silva"
}
}
🔹 Dica prática
Autor
Livro
Categoria (ManyToMany)
API REST funcionando no DRF com GET/POST/PUT/DELETE 🔥
Perfeito! Podemos gerar um PDF com todo esse conteúdo de exemplos e explicações
de Django e DRF. Vou te dar um exemplo de como fazer isso em Python usando a
biblioteca reportlab, que cria PDFs facilmente. 🔥
🔹 Passo 1 – Instalar a biblioteca
pip install reportlab
# Criar PDF
arquivo = "django_drf_exemplos.pdf"
c = [Link](arquivo, pagesize=A4)
largura, altura = A4
# Configurações iniciais
[Link]("Helvetica-Bold", 16)
[Link](2*cm, altura-2*cm, "Exemplos de Django e DRF")
[Link]("Helvetica", 12)
texto = [
"1. ForeignKey – relacionamento um-para-muitos:",
" class Autor([Link]):",
" nome = [Link](max_length=100)",
" class Livro([Link]):",
" titulo = [Link](max_length=100)",
" autor = [Link](Autor,
on_delete=[Link])",
"",
"2. OneToOneField – relacionamento um-para-um:",
" class Perfil([Link]):",
" usuario = [Link]('[Link]',
on_delete=[Link])",
" telefone = [Link](max_length=20)",
"",
"3. ManyToManyField – relacionamento muitos-para-muitos:",
" class Aluno([Link]):",
" nome = [Link](max_length=100)",
" class Curso([Link]):",
" nome = [Link](max_length=100)",
" alunos = [Link](Aluno)",
"",
"Exemplo DRF - nested serializer:",
" class AutorSerializer([Link]):",
" class Meta:",
" model = Autor",
" fields = '__all__'",
"",
" class LivroSerializer([Link]):",
" autor = AutorSerializer()",
" class Meta:",
" model = Livro",
" fields = '__all__'",
]
# Escrever no PDF
y = altura - 3*cm
for linha in texto:
[Link](2*cm, y, linha)
y -= 0.7*cm
if y < 2*cm: # nova página se necessário
[Link]()
y = altura - 2*cm
[Link]("Helvetica", 12)
# Salvar PDF
[Link]()
print(f"PDF gerado: {arquivo}")
on_delete explicações
Exemplo JSON
Estrutura DRF com ViewSet
Diagrama de relacionamento autor ↔ livro
Ah, entendi! 😅
O problema é que no ReportLab, se você só usa drawString, ele não entende
hierarquia de títulos ou títulos grandes – é só texto posicionado na página. Por isso, o
“título” não parece destacado ou relacionado ao conteúdo.
Exemplo completo:
from [Link] import A4
from [Link] import SimpleDocTemplate, Paragraph, Spacer
from [Link] import getSampleStyleSheet
from [Link] import cm
# Criar PDF
arquivo = "django_drf_exemplos_formatado.pdf"
pdf = SimpleDocTemplate(arquivo, pagesize=A4,
rightMargin=2*cm, leftMargin=2*cm,
topMargin=2*cm, bottomMargin=2*cm)
# Estilos
styles = getSampleStyleSheet()
titulo_style = styles['Title']
subtitulo_style = styles['Heading2']
texto_style = styles['BodyText']
# Conteúdo
conteudo = []
# Título
[Link](Paragraph("Exemplos de Django e DRF", titulo_style))
[Link](Spacer(1, 0.5*cm))
# Seção 1
[Link](Paragraph("1. ForeignKey – relacionamento um-para-
muitos", subtitulo_style))
[Link](Paragraph(
"class Autor([Link]):<br/>"
" nome = [Link](max_length=100)<br/>"
"class Livro([Link]):<br/>"
" titulo = [Link](max_length=100)<br/>"
" autor = [Link](Autor,
on_delete=[Link])", texto_style
))
[Link](Spacer(1, 0.5*cm))
# Seção 2
[Link](Paragraph("2. OneToOneField – relacionamento um-para-
um", subtitulo_style))
[Link](Paragraph(
"class Perfil([Link]):<br/>"
" usuario = [Link]('[Link]',
on_delete=[Link])<br/>"
" telefone = [Link](max_length=20)",
texto_style
))
[Link](Spacer(1, 0.5*cm))
# Seção 3
[Link](Paragraph("3. ManyToManyField – relacionamento muitos-
para-muitos", subtitulo_style))
[Link](Paragraph(
"class Aluno([Link]):<br/>"
" nome = [Link](max_length=100)<br/>"
"class Curso([Link]):<br/>"
" nome = [Link](max_length=100)<br/>"
" alunos = [Link](Aluno)", texto_style
))
[Link](Spacer(1, 0.5*cm))
# Gerar PDF
[Link](conteudo)
print(f"PDF gerado: {arquivo}")
Se quiser, eu posso criar uma versão completa do PDF com todos os exemplos que
falámos, incluindo:
Perfeito! Vamos detalhar como o Django cria relacionamentos entre tabelas de forma
clara, incluindo ForeignKey, OneToOneField e ManyToManyField, e como isso se
reflete na API e banco de dados. 🔥
class Autor([Link]):
nome = [Link](max_length=100)
class Livro([Link]):
titulo = [Link](max_length=100)
autor = [Link](Autor, on_delete=[Link])
Como funciona
Tabela Autor:
id nome
1 João Silva
2 Maria
Tabela Livro:
id titulo autor_id
1 Python 1
2 Django DRF 1
3 Segurança 2
Exemplo
class Usuario([Link]):
nome = [Link](max_length=100)
class Perfil([Link]):
usuario = [Link](Usuario, on_delete=[Link])
telefone = [Link](max_length=20)
Cada usuário tem apenas um perfil.
Cada perfil está associado a apenas um usuário.
Se o usuário for deletado, o perfil também será deletado (CASCADE).
Cada registro pode estar relacionado com vários registros de outra tabela.
Django cria uma tabela intermediária automaticamente para armazenar os
relacionamentos.
Exemplo
class Aluno([Link]):
nome = [Link](max_length=100)
class Curso([Link]):
nome = [Link](max_length=100)
alunos = [Link](Aluno)
id curso_id aluno_id
1 1 1
2 1 2
3 2 1
[
{"id":1, "titulo":"Python", "autor":1},
{"id":2, "titulo":"Django", "autor":1}
]
class LivroSerializer([Link]):
autor = AutorSerializer()
class Meta:
model = Livro
fields = '__all__'
[
{
"id":1,
"titulo":"Python",
"autor": {"id":1, "nome":"João Silva"}
}
]
mais outros
Perfeito! Vamos expandir ainda mais com outros tipos de relacionamentos e cenários
no Django que aparecem muito em projetos reais. 🔥
class Livro([Link]):
titulo = [Link](max_length=100)
categoria = [Link](Categoria,
on_delete=models.SET_DEFAULT, default=1)
Quando a categoria original é deletada, o livro recebe uma categoria padrão (ex.:
“Sem Categoria”).
class Aluno([Link]):
nome = [Link](max_length=100)
class Curso([Link]):
nome = [Link](max_length=100)
alunos = [Link](Aluno, through='Matricula')
class Matricula([Link]):
aluno = [Link](Aluno, on_delete=[Link])
curso = [Link](Curso, on_delete=[Link])
data_inscricao = [Link](auto_now_add=True)
nota_final = [Link](max_digits=4, decimal_places=2,
null=True)
class PerfilAvancado([Link]):
usuario = [Link](Usuario, on_delete=[Link])
endereco = [Link](max_length=200)
telefone = [Link](max_length=20)
data_nascimento = [Link]()
class Livro([Link]):
titulo = [Link](max_length=100)
autor = [Link](Autor, on_delete=[Link])
categorias = [Link](Categoria)
[Link]
class CategoriaSerializer([Link]):
class Meta:
model = Categoria
fields = '__all__'
class LivroSerializer([Link]):
autor = AutorSerializer()
categorias = CategoriaSerializer(many=True)
class Meta:
model = Livro
fields = '__all__'
JSON gerado
{
"id":1,
"titulo":"Python Avançado",
"autor":{"id":1, "nome":"João Silva"},
"categorias":[
{"id":1,"nome":"Programação"},
{"id":2,"nome":"Backend"}
]
}
ForeignKey +
Livro → Autor Livro fica sem autor se ele for deletado
SET_NULL
💡 Dica profissional:
Para APIs REST complexas, Nested Serializers do DRF ajudam a mostrar
relacionamentos detalhados em JSON, e on_delete + through ajudam a controlar
integridade do banco de dados.
Se quiser, posso montar um PDF completo com todos esses exemplos, incluindo
diagramas visuais de relacionamentos, para ficares com um material didático
pronto para estudo ou envio.
class Evento([Link]):
titulo = [Link](max_length=100)
descricao = [Link]()
data = [Link]()
usuario = [Link](User, on_delete=[Link])
def __str__(self):
return f"{[Link]} - {[Link]}"
Explicação:
# Criar usuário
user1 = [Link].create_user(username="joao", password="1234")
evento2 = [Link](
titulo="Treinamento",
descricao="Treinamento de DRF",
data=datetime(2026, 3, 26, 10, 0),
usuario=user1
)
Saída:
class Evento([Link]):
titulo = [Link](max_length=100)
descricao = [Link]()
data = [Link]()
participantes = [Link](User,
related_name="eventos_participando")
def __str__(self):
return [Link]
Exemplo de uso:
# Adicionar usuários ao evento
evento = [Link](titulo="Hackathon", descricao="Evento
de programação", data=datetime(2026,3,30,9,0))
user1 = [Link](username="joao")
user2 = [Link].create_user(username="maria", password="1234")
[Link](user1, user2)
# Listar participantes
for u in [Link]():
print([Link])
Saída:
joao
maria
class UserSerializer([Link]):
class Meta:
model = User
fields = ['id', 'username']
class EventoSerializer([Link]):
participantes = UserSerializer(many=True, read_only=True)
class Meta:
model = Evento
fields = ['id', 'titulo', 'descricao', 'data',
'participantes']
💡 Resumo
Se quiser, posso criar uma versão completa de API de eventos + usuários, pronta
para GET, POST, PUT e DELETE no DRF, incluindo autenticação e filtragem por
usuário, que seria um exemplo profissional de sistema real.
mais exmplo
class Evento([Link]):
titulo = [Link](max_length=100)
descricao = [Link]()
data = [Link]()
dono = [Link](User, on_delete=[Link],
related_name="eventos_criados")
participantes = [Link](User,
related_name="eventos_participando")
def __str__(self):
return [Link]
Exemplo de uso:
from datetime import datetime
user1 = [Link](username="joao")
user2 = [Link].create_user(username="maria", password="1234")
evento = [Link](
titulo="Hackathon",
descricao="Evento de programação",
data=datetime(2026, 4, 1, 9, 0),
dono=user1
)
[Link](user1, user2)
# Listar participantes
for u in [Link]():
print([Link])
Saída:
joao
maria
class Evento([Link]):
titulo = [Link](max_length=100)
usuario = [Link](User, on_delete=[Link])
data = [Link]()
recorrencia = [Link](
max_length=10,
choices=[("DIARIO","Diário"),("SEMANAL","Semanal"),("MENSAL","Mensal")
],
default="DIARIO"
)
choices=[("PENDENTE","Pendente"),("CONFIRMADO","Confirmado"),("CANCELA
DO","Cancelado")],
default="PENDENTE"
)
data_confirmacao = [Link](null=True, blank=True)
class Evento([Link]):
titulo = [Link](max_length=100)
descricao = [Link]()
data = [Link]()
participantes = [Link](User, through=Participacao)
Exemplo:
participacao = [Link](
usuario=user2,
evento=evento,
status="CONFIRMADO"
)
# Verificar status
p = [Link](usuario=user2, evento=evento)
print([Link])
Saída:
CONFIRMADO
class ParticipacaoSerializer([Link]):
usuario = [Link]()
class Meta:
model = Participacao
fields = ['usuario', 'status', 'data_confirmacao']
class EventoSerializer([Link]):
participacoes = ParticipacaoSerializer(source='participacao_set',
many=True)
class Meta:
model = Evento
fields = ['id', 'titulo', 'descricao', 'data',
'participacoes']
JSON gerado:
{
"id": 1,
"titulo": "Hackathon",
"descricao": "Evento de programação",
"data": "2026-04-01T09:00:00Z",
"participacoes": [
{"usuario": "joao", "status": "PENDENTE", "data_confirmacao":
null},
{"usuario": "maria", "status": "CONFIRMADO", "data_confirmacao":
"2026-03-24T11:00:00Z"}
]
}
Se quiser, posso criar uma versão completa de API de eventos, pronta para:
Perfeito! 😎 Agora vamos usar modelos existentes do Django e mostrar como associar
eventos a usuários usando [Link] e outros modelos nativos, sem precisar criar
tudo do zero.
class Evento([Link]):
titulo = [Link](max_length=100)
descricao = [Link]()
data = [Link]()
dono = [Link](User, on_delete=[Link],
related_name="eventos_criados")
participantes = [Link](User,
related_name="eventos_participando")
def __str__(self):
return [Link]
✅ Explicação:
class Evento([Link]):
titulo = [Link](max_length=100)
descricao = [Link]()
data = [Link]()
grupos = [Link](Group,
related_name="eventos_grupo")
Aqui, você associa um evento a vários grupos, e todos os usuários dentro do grupo
podem acessar ou participar do evento.
class CustomUser(AbstractUser):
telefone = [Link](max_length=20, blank=True)
departamento = [Link](max_length=50, blank=True)
class Evento([Link]):
titulo = [Link](max_length=100)
descricao = [Link]()
data = [Link]()
dono = [Link](CustomUser, on_delete=[Link])
Isso mantém todos os recursos do User, mas adiciona campos extras, e os eventos
podem usar o CustomUser.
4️⃣ Relacionamento com permissões existentes
Você pode controlar quem vê ou pode editar um evento usando permissões do Django:
class Evento([Link]):
titulo = [Link](max_length=100)
descricao = [Link]()
data = [Link]()
dono = [Link](User, on_delete=[Link])
class Meta:
permissions = [
("pode_editar_evento", "Pode editar evento"),
("pode_ver_evento", "Pode ver evento"),
]
user.user_permissions.add([Link](codename="pode_editar
_evento"))
class UserSerializer([Link]):
class Meta:
model = User
fields = ['id', 'username', 'email']
class EventoSerializer([Link]):
dono = UserSerializer()
participantes = UserSerializer(many=True)
class Meta:
model = Evento
fields = ['id', 'titulo', 'descricao', 'data', 'dono',
'participantes']
JSON resultante:
{
"id": 1,
"titulo": "Hackathon",
"descricao": "Evento de programação",
"data": "2026-04-01T09:00:00Z",
"dono": {"id":1,"username":"joao","email":"joao@[Link]"},
"participantes":[
{"id":1,"username":"joao","email":"joao@[Link]"},
{"id":2,"username":"maria","email":"maria@[Link]"}
]
}
💡 Resumo
Django já tem User, Group e Permission
Você pode usar esses modelos diretamente nos eventos
ForeignKey, ManyToManyField e through funcionam normalmente
DRF converte automaticamente para JSON
Se quiser, posso criar uma API completa de eventos usando User e Group existentes,
com:
Criação de eventos
Associação de participantes e grupos
Controle de permissões
GET/POST/PUT/DELETE pronto para DRF
myproject/
│
├── [Link]
├── myproject/
│ └── [Link], [Link], [Link] ...
├── store/
│ ├── [Link] # Produtos, Clientes, Pedidos
│ ├── [Link] # Conversão para JSON
│ ├── [Link] # ViewSets
│ ├── [Link] # Rotas da API
│ └── migrations/
class Product([Link]):
name = [Link](max_length=100)
price = [Link](max_digits=10, decimal_places=2)
stock = [Link]()
def __str__(self):
return [Link]
class Customer([Link]):
name = [Link](max_length=100)
email = [Link](unique=True)
def __str__(self):
return [Link]
class Order([Link]):
customer = [Link](Customer, on_delete=[Link])
product = [Link](Product, on_delete=[Link])
quantity = [Link]()
created_at = [Link](auto_now_add=True)
class ProductSerializer([Link]):
class Meta:
model = Product
fields = ['id', 'name', 'price', 'stock']
class CustomerSerializer([Link]):
class Meta:
model = Customer
fields = ['id', 'name', 'email']
class OrderSerializer([Link]):
class Meta:
model = Order
fields = ['id', 'customer', 'product', 'quantity',
'created_at']
class ProductViewSet([Link]):
queryset = [Link]()
serializer_class = ProductSerializer
class CustomerViewSet([Link]):
queryset = [Link]()
serializer_class = CustomerSerializer
class OrderViewSet([Link]):
queryset = [Link]()
serializer_class = OrderSerializer
router = DefaultRouter()
[Link](r'products', ProductViewSet)
[Link](r'customers', CustomerViewSet)
[Link](r'orders', OrderViewSet)
urlpatterns = [
path('', include([Link])),
]
urlpatterns = [
path('admin/', [Link]),
path('api/', include('[Link]')),
]
7️⃣ Testando a API
Rode o servidor:
Endpoints:
Se quiser, posso criar uma versão completa da loja com login, JWT, multi-tenant
(várias lojas) e cálculo de total de pedidos para você ver o sistema profissional.
Ah! Perfeito, você está perguntando sobre o método list() que aparece quando
usamos ViewSets no Django REST Framework. Vou explicar detalhadamente.
class ProductViewSet([Link]):
queryset = [Link]()
serializer_class = ProductSerializer
GET /api/products/
class ProductViewSet([Link]):
queryset = [Link]()
serializer_class = ProductSerializer
4️⃣ Resumindo
list() = retornar todos os objetos do model
Chamado automaticamente quando você faz GET no endpoint raiz (/products/)
Você pode sobrescrever para:
o Filtrar resultados
o Ordenar
o Adicionar informações extras no JSON
Se você quiser, posso te mostrar como seria um list() para pedidos de uma loja,
mostrando o total de cada pedido, algo bem real de e-commerce, usando ViewSets +
Serializer.
Ah! Esse erro é bem comum quando se cria um serializer no Django REST
Framework.
Ele diz:
Ou seja: o DRF não encontrou qual model usar dentro do seu serializer.
class productSerializer([Link]):
class Meta:
fields = ['id', 'name', 'price', 'stock'] # ❌ Faltou o model
O DRF exige que você informe o model que esse serializer representa.
2️⃣ A solução
Adicione o model no Meta:
class ProductSerializer([Link]):
class Meta:
model = Product # ✅ Aqui você define o model
fields = ['id', 'name', 'price', 'stock']
Notas importantes:
Se tiver algum erro de digitação no nome do model, o DRF não consegue associar.
[
{
"id": 1,
"name": "Notebook",
"price": "1500.00",
"stock": 10
}
]
Ah! Entendi 😎 — você está usando ViewSet e o endpoint de DELETE não está
aparecendo ou não funciona. Vamos ver os motivos mais comuns e como corrigir.
router = DefaultRouter()
[Link](r'products', ProductViewSet)
urlpatterns = [
path('', include([Link])),
]
Endpoints gerados:
Método URL
GET /products/
POST /products/
GET /products/{id}/
PUT/PATCH /products/{id}/
DELETE /products/{id}/
class ProductViewSet([Link]):
queryset = [Link]()
serializer_class = ProductSerializer
permission_classes = [[Link]] # libera DELETE para
qualquer usuário
Se você quiser, posso montar um ViewSet completo da loja, com GET, POST, PUT,
PATCH, DELETE, pronto para testar, incluindo permissões básicas.
Por exemplo:
Sem permissões, qualquer um poderia fazer qualquer coisa, inclusive deletar todos
os produtos — perigoso! ⚠️
Exemplo básico:
class ProductViewSet([Link]):
queryset = [Link]()
serializer_class = ProductSerializer
permission_classes = [[Link]] # qualquer um pode
acessar
class ProductViewSet([Link]):
queryset = [Link]()
serializer_class = ProductSerializer
permission_classes = [[Link]]
class IsOwner([Link]):
def has_object_permission(self, request, view, obj):
return [Link] == [Link]
Depois, no ViewSet:
class OrderViewSet([Link]):
queryset = [Link]()
serializer_class = OrderSerializer
permission_classes = [IsOwner]
5️⃣ Resumindo
Permissões = regras de quem pode fazer o quê
Configuradas no ViewSet com permission_classes
DRF já vem com permissões prontas (AllowAny, IsAuthenticated, IsAdminUser)
Pode criar permissões personalizadas se precisar de regras específicas
Se você quiser, posso te mostrar como configurar uma API de loja completa com:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE2Nzg5N
jA2MDB9.MF7tL0X8mJYvD_u3M0p5dOZyTz0VjV5h8Zk6lTt8w1A
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.[Link]',
)
}
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(),
name='token_obtain_pair'), # login
path('api/token/refresh/', TokenRefreshView.as_view(),
name='token_refresh'), # atualizar token
]
{
"access": "TOKEN_DE_ACESSO_JWT",
"refresh": "TOKEN_DE_REFRESH"
}
class ProductViewSet([Link]):
queryset = [Link]()
serializer_class = ProductSerializer
permission_classes = [[Link]] # só usuários
logados
POST /api/token/
{
"username": "joao",
"password": "123"
}
2. Recebe tokens:
{
"access": "TOKEN_ACESSO",
"refresh": "TOKEN_REFRESH"
}
3. Acessa a API de produtos:
GET /api/products/
Headers: Authorization: Bearer TOKEN_ACESSO
POST /api/token/refresh/
{
"refresh": "TOKEN_REFRESH"
}
💡 Dica profissional:
Você pode combinar JWT + permissions customizadas para criar uma loja multi-
tenant segura, onde cada usuário só vê seus pedidos ou produtos de sua loja.
Imagine uma empresa que fornece uma plataforma única para academias, lojas de
suplementos e escolas de yoga. Cada cliente da plataforma é um tenant diferente, e
cada tenant tem seus próprios dados, usuários e permissões.
class Tenant([Link]):
name = [Link](max_length=150)
company_type = [Link](max_length=50) # Academia, Loja,
Yoga, etc.
class User(AbstractUser):
tenant = [Link](Tenant, on_delete=[Link],
null=True)
class Product([Link]):
tenant = [Link](Tenant, on_delete=[Link])
name = [Link](max_length=100)
price = [Link](max_digits=10, decimal_places=2)
stock = [Link]()
class ClassSchedule([Link]):
tenant = [Link](Tenant, on_delete=[Link])
class_name = [Link](max_length=100)
instructor = [Link](User, on_delete=[Link])
start_time = [Link]()
end_time = [Link]()
class Order([Link]):
tenant = [Link](Tenant, on_delete=[Link])
customer = [Link](User, on_delete=[Link])
product = [Link](Product, on_delete=[Link])
quantity = [Link]()
created_at = [Link](auto_now_add=True)
4️⃣ Serializers
from rest_framework import serializers
from .models import Product, ClassSchedule, Order, User
class ProductSerializer([Link]):
class Meta:
model = Product
fields = ['id', 'name', 'price', 'stock']
class ClassScheduleSerializer([Link]):
class Meta:
model = ClassSchedule
fields = ['id', 'class_name', 'instructor', 'start_time',
'end_time']
class OrderSerializer([Link]):
class Meta:
model = Order
fields = ['id', 'customer', 'product', 'quantity',
'created_at']
class UserSerializer([Link]):
class Meta:
model = User
fields = ['id', 'username', 'tenant']
class ProductViewSet([Link]):
serializer_class = ProductSerializer
permission_classes = [[Link]]
def get_queryset(self):
return [Link](tenant=[Link])
class ClassScheduleViewSet([Link]):
serializer_class = ClassScheduleSerializer
permission_classes = [[Link]]
def get_queryset(self):
return
[Link](tenant=[Link])
class OrderViewSet([Link]):
serializer_class = OrderSerializer
permission_classes = [[Link]]
def get_queryset(self):
return [Link](tenant=[Link])
Exemplo de endpoints:
Tudo isso usando um único código e banco de dados, isolando os tenants logicamente.
Usuários
Tenants
JWT
Produtos, pedidos, aulas
Fluxo de requisições
Cada tenant funciona como uma empresa isolada, sem acesso aos dados de outro
tenant.
class Tenant([Link]):
name = [Link](max_length=150)
company_type = [Link](max_length=50)
class User(AbstractUser):
tenant = [Link](Tenant, on_delete=[Link],
null=True)
class Product([Link]):
tenant = [Link](Tenant, on_delete=[Link])
name = [Link](max_length=100)
price = [Link](max_digits=10, decimal_places=2)
stock = [Link]()
class Customer([Link]):
tenant = [Link](Tenant, on_delete=[Link])
name = [Link](max_length=100)
email = [Link]()
phone = [Link](max_length=20)
class Order([Link]):
tenant = [Link](Tenant, on_delete=[Link])
customer = [Link](Customer, on_delete=[Link])
product = [Link](Product, on_delete=[Link])
quantity = [Link]()
created_at = [Link](auto_now_add=True)
4️⃣ Serializers
from rest_framework import serializers
from .models import Product, Customer, Order, User
class ProductSerializer([Link]):
class Meta:
model = Product
fields = ['id', 'name', 'price', 'stock']
class CustomerSerializer([Link]):
class Meta:
model = Customer
fields = ['id', 'name', 'email', 'phone']
class OrderSerializer([Link]):
class Meta:
model = Order
fields = ['id', 'customer', 'product', 'quantity',
'created_at']
class UserSerializer([Link]):
class Meta:
model = User
fields = ['id', 'username', 'tenant']
class ProductViewSet([Link]):
serializer_class = ProductSerializer
permission_classes = [[Link]]
def get_queryset(self):
return [Link](tenant=[Link])
class CustomerViewSet([Link]):
serializer_class = CustomerSerializer
permission_classes = [[Link]]
def get_queryset(self):
return
[Link](tenant=[Link])
class OrderViewSet([Link]):
serializer_class = OrderSerializer
permission_classes = [[Link]]
def get_queryset(self):
return [Link](tenant=[Link])
Exemplo de endpoints:
Tudo isso usando uma única aplicação, mas mantendo os dados isolados por tenant.
um sistema escolar
class Tenant([Link]):
name = [Link](max_length=150)
city = [Link](max_length=100)
class User(AbstractUser):
tenant = [Link](Tenant, on_delete=[Link],
null=True)
class Student([Link]):
tenant = [Link](Tenant, on_delete=[Link])
name = [Link](max_length=100)
grade = [Link](max_length=20)
date_of_birth = [Link]()
class Teacher([Link]):
tenant = [Link](Tenant, on_delete=[Link])
name = [Link](max_length=100)
subject = [Link](max_length=50)
class Class([Link]):
tenant = [Link](Tenant, on_delete=[Link])
name = [Link](max_length=50)
teacher = [Link](Teacher, on_delete=[Link])
students = [Link](Student)
4️⃣ Serializers
from rest_framework import serializers
from .models import Student, Teacher, Class, User
class StudentSerializer([Link]):
class Meta:
model = Student
fields = ['id', 'name', 'grade', 'date_of_birth']
class TeacherSerializer([Link]):
class Meta:
model = Teacher
fields = ['id', 'name', 'subject']
class ClassSerializer([Link]):
students = StudentSerializer(many=True, read_only=True)
class Meta:
model = Class
fields = ['id', 'name', 'teacher', 'students']
class UserSerializer([Link]):
class Meta:
model = User
fields = ['id', 'username', 'tenant']
class StudentViewSet([Link]):
serializer_class = StudentSerializer
permission_classes = [[Link]]
def get_queryset(self):
return [Link](tenant=[Link])
class TeacherViewSet([Link]):
serializer_class = TeacherSerializer
permission_classes = [[Link]]
def get_queryset(self):
return [Link](tenant=[Link])
class ClassViewSet([Link]):
serializer_class = ClassSerializer
permission_classes = [[Link]]
def get_queryset(self):
return [Link](tenant=[Link])
Mesmo com várias escolas usando o mesmo sistema, cada tenant é isolado.
8️⃣ Benefícios
Uma plataforma única atende várias escolas (multi-tenant).
Segurança: dados de cada escola são isolados.
Escalabilidade: fácil adicionar novas escolas.
Flexibilidade: diferentes regras por tenant (ex.: quantidade máxima de alunos por
turma).
JWT garante autenticação segura e stateless.
O que é JWT
JWT é um token que você envia junto com cada requisição para a API.
Ele contém informações do usuário, como ID e permissões, de forma segura e
assinada.
Diferente de sessão, não precisa salvar nada no servidor — o token é auto-contido.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE2Nzg5N
jA2MDB9.MF7tL0X8mJYvD_u3M0p5dOZyTz0VjV5h8Zk6lTt8w1A
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.[Link]',
)
}
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(),
name='token_obtain_pair'), # login
path('api/token/refresh/', TokenRefreshView.as_view(),
name='token_refresh'), # atualizar token
]
{
"access": "TOKEN_DE_ACESSO_JWT",
"refresh": "TOKEN_DE_REFRESH"
}
class ProductViewSet([Link]):
queryset = [Link]()
serializer_class = ProductSerializer
permission_classes = [[Link]] # só usuários
logados
POST /api/token/
{
"username": "joao",
"password": "123"
}
2. Recebe tokens:
{
"access": "TOKEN_ACESSO",
"refresh": "TOKEN_REFRESH"
}
3. Acessa a API de produtos:
GET /api/products/
Headers: Authorization: Bearer TOKEN_ACESSO
POST /api/token/refresh/
{
"refresh": "TOKEN_REFRESH"
}
💡 Dica profissional:
Você pode combinar JWT + permissions customizadas para criar uma loja multi-
tenant segura, onde cada usuário só vê seus pedidos ou produtos de sua loja.
Se você quiser, posso criar uma API completa de loja usando ViewSets + JWT +
permissions, já pronta para testar no Postman, com login, registro e CRUD protegido.
Perfeito! Agora vamos juntar tudo: uma API de loja com multi-tenant usando Django
REST Framework + JWT + ViewSets. Vou explicar do zero, passo a passo, para você
entender como funciona e implementar.
Exemplo:
class Tenant([Link]):
name = [Link](max_length=100)
class Product([Link]):
tenant = [Link](Tenant, on_delete=[Link])
name = [Link](max_length=100)
price = [Link](max_digits=10, decimal_places=2)
stock = [Link]()
class Order([Link]):
tenant = [Link](Tenant, on_delete=[Link])
customer = [Link](User, on_delete=[Link])
product = [Link](Product, on_delete=[Link])
quantity = [Link]()
3️⃣ Serializers
from rest_framework import serializers
from .models import Product, Order
class ProductSerializer([Link]):
class Meta:
model = Product
fields = ['id', 'name', 'price', 'stock']
class OrderSerializer([Link]):
class Meta:
model = Order
fields = ['id', 'customer', 'product', 'quantity']
class ProductViewSet([Link]):
serializer_class = ProductSerializer
permission_classes = [[Link]]
def get_queryset(self):
user_tenant = [Link].tenant_id # supondo que cada
User tem tenant_id
return [Link](tenant_id=user_tenant)
class OrderViewSet([Link]):
serializer_class = OrderSerializer
permission_classes = [[Link]]
def get_queryset(self):
user_tenant = [Link].tenant_id
return [Link](tenant_id=user_tenant)
class ProductViewSet([Link]):
serializer_class = ProductSerializer
permission_classes = [[Link]]
def get_queryset(self):
return
[Link](tenant_id=[Link].tenant_id)
Se você quiser, posso montar uma API completa de loja multi-tenant com JWT,
ViewSets, produtos, pedidos e usuários, pronta para testar no Postman.