Perguntas de entrevista Django: ORM, Middleware e DRF em profundidade
Perguntas de entrevista Django sobre otimização do ORM com select_related e prefetch_related, arquitetura de middleware e desempenho de serializers no Django REST Framework, permissões e paginação.

As perguntas de entrevista sobre Django giram em torno de três pilares que separam os candidatos experientes dos demais: o domínio do ORM, a arquitetura de middleware e os padrões de design do Django REST Framework (DRF). Este guia detalha as perguntas exatas que os recrutadores fazem em 2026, com exemplos de código prontos para produção utilizando Django 5.2 LTS e DRF 3.17.
As entrevistas de Django raramente perguntam sobre CRUD básico. O foco mudou para otimização de QuerySets (select_related vs prefetch_related), design de middleware personalizado e desempenho de serializers DRF. Candidatos que conseguem explicar consultas N+1 e escrever viewsets eficientes superam consistentemente aqueles que conhecem apenas as views genéricas.
Perguntas de entrevista sobre o ORM do Django: otimização de QuerySets
A pergunta mais comum sobre o ORM do Django mira no problema N+1. Diante de um modelo com relações de chave estrangeira, o candidato deve demonstrar quando utilizar select_related versus prefetch_related.
# models.py
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=200)
founded_year = models.IntegerField()
class Developer(models.Model):
name = models.CharField(max_length=200)
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="developers")
skills = models.ManyToManyField("Skill", related_name="developers")
class Skill(models.Model):
name = models.CharField(max_length=100)
category = models.CharField(max_length=50)A diferença entre os dois métodos está no tipo de relacionamento que está sendo percorrido.
# queries.py — Abordagem correta para ForeignKey (objeto único)
developers = Developer.objects.select_related("company").all()
# Gera UMA única consulta SQL com JOIN
# SELECT developer.*, company.* FROM developer INNER JOIN company ...
# Abordagem correta para ManyToMany (múltiplos objetos)
developers = Developer.objects.prefetch_related("skills").all()
# Gera DUAS consultas SQL:
# 1. SELECT * FROM developer
# 2. SELECT * FROM skill INNER JOIN developer_skills WHERE developer_id IN (...)select_related realiza um JOIN SQL e funciona com campos ForeignKey e OneToOneField. prefetch_related executa uma consulta separada e funciona com ManyToManyField e relações ForeignKey inversas. Confundir os dois causa JOINs desnecessários em grandes conjuntos de dados ou o temido padrão N+1.
ORM avançado: Managers personalizados e encadeamento de QuerySets
Os entrevistadores frequentemente pedem aos candidatos que escrevam um manager personalizado que encapsule a lógica de negócio. O objetivo é verificar se o candidato compreende o padrão manager do Django e consegue escrever interfaces de consulta reutilizáveis.
# managers.py
from django.db import models
from django.utils import timezone
class ActiveDeveloperQuerySet(models.QuerySet):
def active(self):
"""Filter developers who logged in within the last 30 days."""
cutoff = timezone.now() - timezone.timedelta(days=30)
return self.filter(last_login__gte=cutoff)
def senior(self):
"""Filter developers with 5+ years of experience."""
return self.filter(years_experience__gte=5)
def by_skill(self, skill_name):
"""Filter developers by a specific skill."""
return self.filter(skills__name=skill_name)
class ActiveDeveloperManager(models.Manager):
def get_queryset(self):
return ActiveDeveloperQuerySet(self.model, using=self._db)
def active(self):
return self.get_queryset().active()A pergunta de acompanhamento chave: "Por que usar um QuerySet personalizado em vez de apenas um Manager?" A resposta está no encadeamento. Os métodos de um QuerySet personalizado podem ser encadeados, enquanto os métodos de um Manager não podem ser encadeados após a primeira chamada.
# usage.py — Encadeamento de QuerySets em ação
# Isso funciona porque cada método retorna um QuerySet
senior_python_devs = (
Developer.active_objects # manager personalizado
.active() # método ActiveDeveloperQuerySet
.senior() # encadeia outro método QuerySet
.by_skill("Python") # encadeia um terceiro método
.select_related("company") # métodos padrão do QuerySet continuam funcionando
)O Django 5.2 introduziu o CompositePrimaryKey, uma funcionalidade aguardada há muito tempo para modelos que precisam de chaves primárias com múltiplas colunas. Perguntas de entrevista sobre esse recurso estão se tornando cada vez mais comuns, especialmente para candidatos que trabalham com bancos de dados legados ou esquemas de data warehouse.
Perguntas de entrevista sobre middleware Django: pipeline requisição-resposta
As perguntas sobre middleware testam a compreensão do ciclo de vida requisição-resposta do Django. A pergunta padrão: "Explique a ordem em que o middleware processa uma requisição e uma resposta."
A resposta segue um padrão rigoroso. Durante uma requisição, as classes de middleware são executadas de cima para baixo conforme definido em MIDDLEWARE. Durante uma resposta, são executadas de baixo para cima. Essa arquitetura em camadas tipo cebola significa que o primeiro middleware da lista envolve todo o restante.
# middleware.py
import time
import logging
from django.http import JsonResponse
logger = logging.getLogger(__name__)
class RequestTimingMiddleware:
"""Logs the time taken to process each request."""
def __init__(self, get_response):
self.get_response = get_response # next middleware or view
def __call__(self, request):
start_time = time.monotonic()
response = self.get_response(request) # passes to next layer
duration_ms = (time.monotonic() - start_time) * 1000
logger.info(
"method=%s path=%s status=%d duration=%.2fms",
request.method,
request.path,
response.status_code,
duration_ms,
)
return responseUma pergunta de acompanhamento comum: "Como curto-circuitar a cadeia de middleware?" Retornar uma HttpResponse de __call__ antes de chamar self.get_response(request) interrompe a cadeia completamente. Os middleware restantes e a view nunca são executados.
# middleware.py — Rate limiting com curto-circuito
from django.core.cache import cache
class RateLimitMiddleware:
"""Blocks requests exceeding 100 per minute per IP."""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
ip = request.META.get("REMOTE_ADDR")
cache_key = f"rate_limit:{ip}"
request_count = cache.get(cache_key, 0)
if request_count >= 100:
return JsonResponse( # short-circuits — view never executes
{"error": "Rate limit exceeded. Try again in 60 seconds."},
status=429,
)
cache.set(cache_key, request_count + 1, timeout=60)
return self.get_response(request)Hooks de middleware: process_view, process_exception e process_template_response
Além de __call__, o middleware do Django suporta três métodos hook opcionais. Os entrevistadores utilizam esses métodos para avaliar a profundidade do conhecimento.
# middleware.py — Middleware completo com todos os hooks
class AuditMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_view(self, request, view_func, view_args, view_kwargs):
"""Called after URL resolution, before the view executes."""
logger.info("Calling view: %s", view_func.__name__)
return None # returning None continues normal processing
def process_exception(self, request, exception):
"""Called only if the view raises an exception."""
logger.error("View exception: %s", exception, exc_info=True)
return None # returning None lets Django's default handling proceed
def process_template_response(self, request, response):
"""Called if the response has a render() method (TemplateResponse)."""
response.context_data["audit_timestamp"] = time.time()
return response # must return a response with render()process_view é acionado após a resolução de URL, mas antes da view. Retornar None continua a execução; retornar uma HttpResponse curto-circuita. process_exception é acionado apenas em exceções não tratadas. process_template_response é acionado apenas para objetos TemplateResponse, não para HttpResponse regulares.
Pronto para mandar bem nas entrevistas de Django?
Pratique com nossos simuladores interativos, flashcards e testes tecnicos.
Perguntas de entrevista DRF: desempenho de serializers
As perguntas sobre serializers do Django REST Framework focam na serialização aninhada e nas implicações de desempenho das diferentes abordagens. A pergunta mais frequente: "Como lidar com relacionamentos aninhados sem causar consultas N+1?"
# serializers.py
from rest_framework import serializers
from .models import Developer, Company, Skill
class SkillSerializer(serializers.ModelSerializer):
class Meta:
model = Skill
fields = ["name", "category"]
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = ["name", "founded_year"]
class DeveloperSerializer(serializers.ModelSerializer):
company = CompanySerializer(read_only=True) # nested FK
skills = SkillSerializer(many=True, read_only=True) # nested M2M
class Meta:
model = Developer
fields = ["id", "name", "company", "skills"]O serializer sozinho não resolve o desempenho. O ViewSet precisa otimizar o queryset.
# views.py
from rest_framework import viewsets
from .models import Developer
from .serializers import DeveloperSerializer
class DeveloperViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = DeveloperSerializer
def get_queryset(self):
return (
Developer.objects
.select_related("company") # JOIN for FK
.prefetch_related("skills") # separate query for M2M
.order_by("-id")
)Sem select_related e prefetch_related no ViewSet, cada desenvolvedor serializado dispara consultas individuais para sua empresa e habilidades. Em uma lista de 50 desenvolvedores, isso significa 1 + 50 + 50 = 101 consultas em vez de 3.
Permissões e autenticação personalizadas no DRF
Uma pergunta frequente em entrevistas sobre DRF: "Escreva uma permissão personalizada que restrinja o acesso com base no papel do usuário e no proprietário do objeto."
# permissions.py
from rest_framework.permissions import BasePermission
class IsOwnerOrAdmin(BasePermission):
"""
Object-level permission:
- Admin users can access any object
- Regular users can only access objects they own
"""
message = "Access restricted to the object owner or admin users."
def has_object_permission(self, request, view, obj):
if request.user.is_staff:
return True
# Assumes the model has an 'owner' field pointing to User
return obj.owner == request.user# views.py — Applying custom permissions
from rest_framework import viewsets, permissions
from .permissions import IsOwnerOrAdmin
class ProjectViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated, IsOwnerOrAdmin]
def get_queryset(self):
# Non-admin users only see their own projects
if self.request.user.is_staff:
return Project.objects.all()
return Project.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user) # auto-assign ownerA nuance que os entrevistadores procuram: has_permission é executado em cada requisição (nível lista), enquanto has_object_permission é executado apenas quando get_object() é chamado (nível detalhe). Esquecer de sobrescrever get_queryset para as views de lista cria uma brecha de segurança onde usuários podem ver objetos que não lhes pertencem.
Depender apenas de has_object_permission sem filtrar o queryset deixa o endpoint de lista desprotegido. Sempre se deve combinar permissões a nível de objeto com um get_queryset filtrado para aplicar o controle de acesso tanto nas views de lista quanto de detalhe.
Throttling e padrões de paginação no DRF
Throttling e paginação são perguntas de acompanhamento padrão. Os entrevistadores querem ver que o candidato entende a configuração de API pronta para produção.
# settings.py — Production DRF configuration
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": [
"rest_framework.throttling.AnonRateThrottle",
"rest_framework.throttling.UserRateThrottle",
],
"DEFAULT_THROTTLE_RATES": {
"anon": "20/minute", # unauthenticated users
"user": "200/minute", # authenticated users
},
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.CursorPagination",
"PAGE_SIZE": 25,
}# pagination.py — Custom cursor pagination for consistent ordering
from rest_framework.pagination import CursorPagination
class CreatedAtCursorPagination(CursorPagination):
page_size = 25
ordering = "-created_at" # must be a unique, sequential field
cursor_query_param = "cursor" # ?cursor=abc123A paginação por cursor supera a paginação por offset em grandes conjuntos de dados porque não precisa contar o número total de linhas. A contrapartida: os clientes não podem pular para uma página arbitrária. Esta é a resposta esperada quando os entrevistadores perguntam "Por que escolher paginação por cursor em vez de paginação por número de página?"
Conclusão
Pontos-chave para a preparação para entrevistas Django:
- Otimização do ORM: sempre associar o método de consulta ao tipo de relacionamento.
select_relatedpara ForeignKey/OneToOne,prefetch_relatedpara ManyToMany e FK inversa. QuerySets personalizados permitem lógica de negócio encadeável e reutilizável. - Arquitetura de middleware: a requisição flui de cima para baixo, a resposta de baixo para cima. Curto-circuitar retornando uma resposta antes de
get_response()é um padrão fundamental para rate limiting, verificações de autenticação e validação de requisições. - Desempenho de serializers DRF: serializers aninhados exigem otimização explícita do queryset no ViewSet. Sem
select_related/prefetch_related, a serialização causa consultas N+1 em escala. - Permissões DRF: combinar
has_object_permissioncom umget_querysetfiltrado para aplicar controle de acesso nos endpoints de lista e detalhe. Permissões a nível de objeto sozinhas deixam as views de lista desprotegidas. - Throttling e paginação: a paginação por cursor escala melhor que offset em tabelas grandes. Configurar taxas de throttling separadas para usuários anônimos e autenticados.
Para consolidar esses conhecimentos, recomenda-se praticar com perguntas de entrevista sobre o ORM do Django e perguntas sobre middleware Django no SharpSkill antes da entrevista real.
Comece a praticar!
Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.
Tags
Compartilhar
Artigos relacionados

Django 5.2: Middleware Personalizado e Tratamento de Signals para Entrevistas Técnicas
Guia completo sobre middleware personalizado e signals no Django 5.2. Implementação de middleware de logging, middleware assíncrono, signals pre_save/post_save e perguntas frequentes de entrevista.

Django 6.0 em 2026: Chaves Primárias Compostas, Tarefas em Background e Perguntas de Entrevista
Django 6.0 em 2026: chaves primárias compostas, tarefas em background, template partials, middleware CSP nativo e perguntas de entrevista técnica.

Django e Celery: Processamento Assíncrono de Tarefas e Perguntas de Entrevista 2026
Guia completo de Django e Celery com configuração, filas, Celery Beat, deploy em produção e perguntas de entrevista técnica para desenvolvedores Python em 2026.