# Django 5.2: Middleware Personalizado y Manejo de Señales para Entrevistas Técnicas > Guía completa sobre middleware personalizado y señales en Django 5.2. Implementación de middleware de logging, middleware asíncrono, señales pre_save/post_save y preguntas frecuentes de entrevista. - Published: 2026-04-29 - Updated: 2026-04-29 - Author: SharpSkill - Tags: django, python, middleware, signals, interview - Reading time: 9 min --- Los middleware personalizados y el manejo de señales representan dos pilares fundamentales en el desarrollo profesional con Django. Durante las entrevistas técnicas para posiciones de desarrollo backend, estos temas aparecen frecuentemente porque demuestran comprensión profunda del ciclo de vida de las solicitudes HTTP y la arquitectura orientada a eventos. Django 5.2, lanzado como versión LTS (Long Term Support), introduce mejoras significativas en el soporte asíncrono que todo desarrollador debe dominar. > El middleware procesa las solicitudes de arriba hacia abajo en la configuración de MIDDLEWARE y las respuestas de abajo hacia arriba. Las señales siguen el patrón publicador-suscriptor, permitiendo que componentes desacoplados reaccionen a eventos específicos del sistema. ## Arquitectura del Middleware en Django 5.2 El sistema de middleware actúa como una serie de capas que envuelven la vista principal de Django. Cada middleware puede inspeccionar o modificar tanto la solicitud entrante como la respuesta saliente. Esta arquitectura permite implementar funcionalidades transversales sin contaminar la lógica de negocio. La estructura básica de un middleware sigue un patrón consistente que los entrevistadores esperan que los candidatos conozcan: ```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 ``` El método `__init__` se ejecuta una única vez cuando el servidor inicia, mientras que `__call__` se invoca en cada solicitud HTTP. Esta distinción resulta crítica para optimizar el rendimiento y evitar inicializaciones costosas repetidas. ## Implementación de Middleware para Logging de Solicitudes Un caso de uso común en aplicaciones de producción involucra el registro detallado de todas las solicitudes HTTP. Este middleware captura métricas de tiempo, códigos de estado y direcciones IP, información invaluable para debugging y monitoreo: ```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 ``` El método `process_exception` constituye un hook especial que Django invoca únicamente cuando una vista lanza una excepción no manejada. Retornar `None` permite que el manejo de excepciones predeterminado continúe, mientras que retornar un objeto `HttpResponse` cortocircuita el proceso. ## Orden de Ejecución del Middleware El orden en que se declaran los middleware en `settings.py` determina su secuencia de ejecución. Los middleware de Django deben mantener un orden específico para funcionar correctamente: ```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', ] ``` Las preguntas de entrevista sobre django middleware frecuentemente exploran escenarios donde el orden incorrecto causa comportamientos inesperados. Por ejemplo, colocar un middleware de autenticación personalizado antes de `SessionMiddleware` resultaría en errores porque la sesión no estaría disponible. ## Middleware Asíncrono en Django 5.2 Una de las características más relevantes de Django 5.2 para entrevistas técnicas es el soporte mejorado para middleware asíncrono. Las aplicaciones modernas requieren manejo eficiente de operaciones I/O-bound, y el middleware asíncrono permite procesar solicitudes sin bloquear el event loop: ```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 ``` Los atributos `async_capable` y `sync_capable` indican a Django las capacidades del middleware. Cuando `sync_capable` es `False`, Django garantiza que el middleware solo se ejecutará en contexto asíncrono, evitando la penalización de rendimiento asociada con la sincronización entre modos. > Django 5.2 es una versión LTS (Long Term Support) con soporte garantizado hasta abril de 2028. Esta versión consolida las mejoras de rendimiento asíncrono introducidas en versiones anteriores y las optimiza para uso en producción. ## Sistema de Señales de Django Las señales de Django implementan el patrón Observer, permitiendo que aplicaciones desacopladas respondan a acciones que ocurren en otras partes del sistema. Este mecanismo resulta esencial para mantener la separación de responsabilidades. ### Señales Integradas: post_save El caso de uso más común involucra la señal `post_save` para ejecutar lógica después de guardar un modelo: ```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, ) ``` El parámetro `created` distingue entre inserciones y actualizaciones, permitiendo ejecutar lógica condicional basada en el tipo de operación. ### Señales pre_save para Validación La señal `pre_save` permite modificar instancias antes de persistirlas en la base de datos. Un patrón común genera slugs únicos automáticamente: ```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 ``` > Las operaciones QuerySet.update() y bulk_create() no disparan señales de modelo. Estas operaciones trabajan directamente a nivel de base de datos, evitando el ORM de Django. Para casos donde las señales son críticas, se debe iterar sobre los objetos y llamar save() individualmente, o implementar lógica alternativa. ## Registro de Señales en AppConfig Django requiere que las señales se importen durante la inicialización de la aplicación. El método `ready()` de `AppConfig` proporciona el punto de entrada apropiado: ```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 ``` Esta práctica asegura que los receptores de señales se registren exactamente una vez cuando Django inicia, evitando duplicación de handlers y comportamientos inesperados. ## Creación de Señales Personalizadas Para escenarios de negocio complejos, Django permite definir señales personalizadas que comunican eventos específicos del dominio: ```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}, ) ``` Este patrón desacopla completamente la lógica de procesamiento de pedidos de la notificación al cliente. Agregar nuevos comportamientos (analytics, inventario, loyalty points) solo requiere registrar nuevos receptores sin modificar el código existente. ## Comparación: Middleware vs Señales Comprender cuándo utilizar cada mecanismo constituye una pregunta frecuente en entrevistas sobre Django: | Aspecto | Middleware | Señales | |---------|------------|--------| | Alcance | Solicitudes/Respuestas HTTP | Eventos del modelo y sistema | | Ejecución | Cada solicitud HTTP | Solo cuando ocurre el evento | | Orden | Determinístico (configuración) | No garantizado entre receptores | | Caso de uso | Autenticación, logging, CORS | Efectos secundarios de modelos | | Rendimiento | Impacto en cada request | Solo en operaciones específicas | | Acoplamiento | Con el ciclo HTTP | Con eventos de Django | ## Preguntas Frecuentes en Entrevistas Técnicas Las django interview questions sobre estos temas suelen explorar escenarios prácticos: **Pregunta**: ¿Cómo implementarías rate limiting por usuario? El middleware resulta ideal porque necesita interceptar cada solicitud antes de que llegue a la vista. Se puede utilizar el cache de Django para rastrear conteos por IP o usuario autenticado. **Pregunta**: ¿Cuándo preferirías señales sobre sobrescribir el método save()? Las señales mantienen la separación de responsabilidades cuando múltiples aplicaciones necesitan reaccionar al mismo evento. Sobrescribir `save()` acopla la lógica al modelo específico. **Pregunta**: ¿Cómo manejarías errores en receptores de señales? Los errores en receptores propagan hacia el código que envió la señal. Para receptores críticos, implementar try/except con logging adecuado previene que un receptor fallido afecte a otros. ## Mejores Prácticas para Producción El desarrollo profesional con Django 5.2 requiere adherirse a patrones probados. Los middleware deben ser ligeros y evitar operaciones bloqueantes prolongadas. Las señales deben documentar claramente qué eventos emiten y qué efectos secundarios producen. Para aplicaciones que manejan alto volumen de tráfico, considerar el uso de Celery para delegar el trabajo pesado de los receptores de señales a tareas asíncronas. Esto mantiene la respuesta HTTP rápida mientras el procesamiento continúa en background. La combinación efectiva de middleware y señales permite construir aplicaciones Django escalables, mantenibles y testables. Dominar estos conceptos diferencia a los desarrolladores senior de aquellos con experiencia superficial en el framework. ## Conclusión El middleware personalizado y las señales de Django representan herramientas complementarias para diferentes capas de la arquitectura. El middleware opera en el ciclo de vida HTTP, ideal para concerns transversales como autenticación, logging y modificación de headers. Las señales operan en el ciclo de vida de los modelos y eventos del sistema, perfectas para mantener componentes desacoplados que reaccionan a cambios de estado. Django 5.2 features como el soporte mejorado para middleware asíncrono reflejan la evolución del framework hacia arquitecturas modernas. Los desarrolladores que demuestran comprensión profunda de estos mecanismos durante las entrevistas técnicas evidencian experiencia práctica con aplicaciones Django de producción y capacidad para diseñar sistemas mantenibles a largo plazo. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/es/blog/django/django-5-2-custom-middleware-signals