# 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. - Published: 2026-04-29 - Updated: 2026-04-29 - Author: SharpSkill - Tags: django, python, middleware, signals, interview - Reading time: 9 min --- Django 5.2 representa um marco significativo para desenvolvedores Python que buscam construir aplicações web robustas e escaláveis. Entre os recursos mais explorados em entrevistas técnicas para posições backend, o domínio de middleware e signals se destaca como diferencial competitivo. Esses dois mecanismos permitem interceptar e modificar o fluxo de requisições HTTP e responder a eventos do ciclo de vida dos modelos de forma desacoplada e elegante. > O middleware processa requisições de cima para baixo na lista MIDDLEWARE do settings.py, enquanto signals seguem o padrão publish-subscribe, permitindo que múltiplos receivers respondam a um único evento. Compreender essa distinção é fundamental para aplicar cada recurso no contexto adequado. ## Fundamentos de Middleware no Django 5.2 O middleware no Django funciona como uma camada de processamento que envolve cada requisição HTTP antes de chegar à view e cada resposta antes de retornar ao cliente. Cada classe de middleware tem a oportunidade de modificar, validar ou rejeitar requisições, tornando-se essencial para implementar funcionalidades transversais como logging, autenticação e rate limiting. A estrutura básica de um middleware segue um padrão específico que todo desenvolvedor Django deve conhecer: ```python # middleware.py - Basic middleware structure class SimpleMiddleware: def __init__(self, get_response): self.get_response = get_response # One-time configuration happens here at server start def __call__(self, request): # Code executed BEFORE the view (and later middleware) response = self.get_response(request) # Code executed AFTER the view (on the way back) return response ``` O método `__init__` executa apenas uma vez durante a inicialização do servidor, enquanto `__call__` processa cada requisição individualmente. Essa separação permite otimizações de performance ao carregar configurações pesadas apenas no startup. ## Implementando Middleware de Logging para Produção Em ambientes de produção, monitorar o tempo de resposta e capturar exceções de forma estruturada representa uma necessidade crítica. O exemplo a seguir demonstra um middleware de logging profissional que registra métricas essenciais para observabilidade: ```python # apps/core/middleware.py import logging import time logger = logging.getLogger('django.request') class RequestLoggingMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): start_time = time.monotonic() # Attach metadata before view processing request.start_time = start_time response = self.get_response(request) duration = time.monotonic() - start_time logger.info( 'method=%s path=%s status=%d duration=%.3fs ip=%s', request.method, request.get_full_path(), response.status_code, duration, request.META.get('REMOTE_ADDR'), ) return response def process_exception(self, request, exception): # Called only when the view raises an exception duration = time.monotonic() - getattr(request, 'start_time', 0) logger.error( 'method=%s path=%s exception=%s duration=%.3fs', request.method, request.get_full_path(), str(exception), duration, ) return None # Let Django's default exception handling continue ``` O hook `process_exception` merece atenção especial em django interview questions. Esse método executa apenas quando a view lança uma exceção não tratada, permitindo logging granular de erros antes que o handler padrão do Django assuma o controle. ## Ordenação de Middleware: Detalhes que Fazem Diferença A ordem de declaração no `settings.py` impacta diretamente o comportamento da aplicação. Middlewares executam de cima para baixo no processamento da requisição e de baixo para cima no retorno da resposta: ```python # settings.py - Middleware ordering matters MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', # Custom middleware placed after Django's core stack 'apps.core.middleware.RequestLoggingMiddleware', ] ``` O `RequestLoggingMiddleware` posicionado após o stack do Django garante acesso ao usuário autenticado e à sessão estabelecida. Posicioná-lo antes de `AuthenticationMiddleware` resultaria em logs sem informações de autenticação. ## Middleware Assíncrono no Django 5.2 Entre os django 5.2 features mais relevantes para aplicações modernas, o suporte aprimorado a middleware assíncrono permite otimizar operações I/O-bound sem bloquear workers do servidor: ```python # apps/core/middleware.py import asyncio import time class AsyncTimingMiddleware: # Mark this middleware as async-capable async_capable = True sync_capable = False def __init__(self, get_response): self.get_response = get_response async def __call__(self, request): start = time.monotonic() # get_response is awaitable in async context response = await self.get_response(request) duration = time.monotonic() - start response['X-Request-Duration'] = f'{duration:.4f}s' return response ``` Os atributos `async_capable` e `sync_capable` indicam ao Django como o middleware deve ser executado. Definir `sync_capable = False` força o uso exclusivo em contexto assíncrono, evitando overhead de conversão. ## Sistema de Signals: Desacoplamento e Extensibilidade Django signals implementam o padrão Observer, permitindo que componentes independentes reajam a eventos sem conhecimento direto uns dos outros. O signal `post_save` representa o caso de uso mais comum em aplicações Django: ```python # apps/accounts/signals.py from django.db.models.signals import post_save from django.dispatch import receiver from django.contrib.auth import get_user_model from apps.accounts.models import UserProfile User = get_user_model() @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): # 'created' is True only on INSERT, False on UPDATE if created: UserProfile.objects.create( user=instance, display_name=instance.get_full_name() or instance.username, ) ``` O parâmetro `created` diferencia inserções de atualizações, evitando a criação duplicada de perfis. Essa verificação aparece frequentemente em django interview questions sobre boas práticas com signals. > Operações como QuerySet.update() e bulk_create() não disparam signals post_save ou pre_save por questões de performance. Para garantir a execução de lógica de negócio nesses casos, considere chamar receivers manualmente ou utilizar signals customizados no service layer. ## Geração Automática de Slugs com pre_save O signal `pre_save` executa antes da persistência no banco de dados, tornando-o ideal para validações e transformações de dados: ```python # apps/blog/signals.py from django.db.models.signals import pre_save from django.dispatch import receiver from django.utils.text import slugify from apps.blog.models import Article @receiver(pre_save, sender=Article) def auto_generate_slug(sender, instance, **kwargs): if not instance.slug: base_slug = slugify(instance.title) slug = base_slug counter = 1 # Ensure slug uniqueness while Article.objects.filter(slug=slug).exclude(pk=instance.pk).exists(): slug = f'{base_slug}-{counter}' counter += 1 instance.slug = slug ``` A lógica de unicidade implementada evita colisões de URLs, incrementando um contador quando necessário. O uso de `exclude(pk=instance.pk)` garante que atualizações do próprio artigo não gerem conflitos falsos. ## Registro de Signals no AppConfig A conexão entre receivers e signals deve ocorrer durante a inicialização da aplicação. O método `ready()` do AppConfig fornece o hook adequado: ```python # apps/accounts/apps.py from django.apps import AppConfig class AccountsConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'apps.accounts' def ready(self): # Import signals module to register receivers import apps.accounts.signals # noqa: F401 ``` O comentário `noqa: F401` silencia avisos de import não utilizado, já que o efeito colateral do import registra os receivers via decoradores. ## Signals Customizados para Lógica de Domínio Além dos signals built-in do Django, a criação de signals customizados permite modelar eventos específicos do domínio da aplicação: ```python # apps/orders/signals.py from django.dispatch import Signal # Define custom signals with documentation order_completed = Signal() # Sent after payment confirmation order_refunded = Signal() # Sent after refund processing # apps/orders/services.py from apps.orders.signals import order_completed def complete_order(order): order.status = 'completed' order.save() # Dispatch signal with relevant context order_completed.send( sender=order.__class__, order=order, total=order.total_amount, ) # apps/notifications/receivers.py from django.dispatch import receiver from apps.orders.signals import order_completed @receiver(order_completed) def send_order_confirmation_email(sender, order, **kwargs): # Email logic decoupled from order processing from apps.notifications.services import send_email send_email( to=order.customer.email, template='order_confirmation', context={'order': order}, ) ``` Essa arquitetura desacopla completamente o processamento de pedidos do envio de notificações, facilitando testes unitários e permitindo adicionar novos receivers sem modificar o código de negócio existente. > Django 5.2 é uma versão LTS (Long Term Support), com suporte garantido até abril de 2028. Isso torna o investimento em aprender suas funcionalidades especialmente valioso para projetos de longo prazo e preparação para entrevistas técnicas. ## Middleware vs Signals: Quando Utilizar Cada Um A escolha entre middleware e signals depende do contexto e do tipo de operação necessária. A tabela comparativa abaixo esclarece os cenários de uso: | Aspecto | Middleware | Signals | |---------|-----------|--------| | Escopo | Requisições HTTP | Eventos do ORM e customizados | | Execução | Toda requisição (configurável) | Apenas quando o evento ocorre | | Acesso | Request/Response completos | Instância do modelo e metadados | | Casos de uso | Autenticação, logging, CORS, rate limiting | Criação de perfil, auditoria, cache invalidation | | Performance | Impacto em toda requisição | Impacto apenas no evento específico | | Testabilidade | Requer mock de request/response | Pode testar receivers isoladamente | Django middleware atende melhor necessidades transversais de infraestrutura, enquanto django signals resolvem problemas de desacoplamento no domínio da aplicação. ## Perguntas Frequentes em Entrevistas Técnicas Recrutadores frequentemente exploram cenários práticos envolvendo middleware e signals. Questões comuns incluem: diferenças entre `process_view` e `process_exception`, impacto de signals síncronos na performance de requisições, e estratégias para evitar loops infinitos em receivers que modificam o modelo emissor. A compreensão profunda desses mecanismos demonstra maturidade técnica e capacidade de projetar sistemas extensíveis. Candidatos que articulam trade-offs entre acoplamento, testabilidade e performance destacam-se em processos seletivos competitivos. ## Conclusão O domínio de django middleware e django signals representa competência técnica valorizada em entrevistas para posições Django. A versão 5.2 consolida esses recursos com melhorias em suporte assíncrono e estabilidade de longo prazo como versão LTS. A aplicação prática dos conceitos apresentados, desde middleware de logging até signals customizados para eventos de domínio, demonstra capacidade de construir aplicações Django profissionais e escaláveis. O investimento em compreender esses padrões retorna tanto em produtividade no dia a dia quanto em sucesso em processos seletivos técnicos. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/django/django-5-2-custom-middleware-signals