Preguntas de entrevista Django: ORM, Middleware y DRF a fondo
Preguntas de entrevista Django sobre optimización del ORM con select_related y prefetch_related, arquitectura de middleware y rendimiento de serializers en Django REST Framework, permisos y paginación.

Las preguntas de entrevista sobre Django giran en torno a tres pilares que diferencian a los candidatos con experiencia del resto: el dominio del ORM, la arquitectura de middleware y los patrones de diseño de Django REST Framework (DRF). Esta guía desglosa las preguntas exactas que formulan los reclutadores en 2026, con ejemplos de código listos para producción utilizando Django 5.2 LTS y DRF 3.17.
Las entrevistas de Django rara vez preguntan sobre CRUD básico. El enfoque se ha trasladado a la optimización de QuerySets (select_related vs prefetch_related), el diseño de middleware personalizado y el rendimiento de los serializers DRF. Los candidatos que pueden explicar las consultas N+1 y escribir viewsets eficientes superan constantemente a quienes solo conocen las vistas genéricas.
Preguntas de entrevista sobre el ORM de Django: optimización de QuerySets
La pregunta más común sobre el ORM de Django apunta al problema N+1. Dado un modelo con relaciones de clave foránea, el candidato debe demostrar cuándo utilizar select_related en lugar de 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)La diferencia entre ambos métodos radica en el tipo de relación que se recorre.
# queries.py — Approche correcte pour ForeignKey (objet unique)
developers = Developer.objects.select_related("company").all()
# Genera UNA sola consulta SQL con JOIN
# SELECT developer.*, company.* FROM developer INNER JOIN company ...
# Enfoque correcto para ManyToMany (múltiples objetos)
developers = Developer.objects.prefetch_related("skills").all()
# Genera DOS consultas SQL:
# 1. SELECT * FROM developer
# 2. SELECT * FROM skill INNER JOIN developer_skills WHERE developer_id IN (...)select_related realiza un JOIN SQL y funciona con campos ForeignKey y OneToOneField. prefetch_related ejecuta una consulta separada y funciona con ManyToManyField y relaciones ForeignKey inversas. Confundir ambos provoca JOINs innecesarios en conjuntos de datos grandes o el temido patrón N+1.
ORM avanzado: Managers personalizados y encadenamiento de QuerySets
Los entrevistadores suelen pedir a los candidatos que escriban un manager personalizado que encapsule la lógica de negocio. El objetivo es verificar que el candidato comprende el patrón manager de Django y puede escribir interfaces de consulta reutilizables.
# 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()La pregunta de seguimiento clave: "¿Por qué usar un QuerySet personalizado en lugar de solo un Manager?" La respuesta está en el encadenamiento. Los métodos de un QuerySet personalizado pueden encadenarse, mientras que los métodos de un Manager no pueden encadenarse después de la primera llamada.
# usage.py — Encadenamiento de QuerySets en acción
# Esto funciona porque cada método retorna un QuerySet
senior_python_devs = (
Developer.active_objects # manager personalizado
.active() # método ActiveDeveloperQuerySet
.senior() # encadena otro método QuerySet
.by_skill("Python") # encadena un tercer método
.select_related("company") # los métodos estándar de QuerySet siguen funcionando
)Django 5.2 introdujo CompositePrimaryKey, una funcionalidad largamente esperada para modelos que necesitan claves primarias de múltiples columnas. Las preguntas de entrevista sobre esta característica son cada vez más frecuentes, especialmente para candidatos que trabajan con bases de datos heredadas o esquemas de data warehouse.
Preguntas de entrevista sobre middleware Django: pipeline solicitud-respuesta
Las preguntas sobre middleware evalúan la comprensión del ciclo de vida solicitud-respuesta de Django. La pregunta estándar: "Explique el orden en que el middleware procesa una solicitud y una respuesta."
La respuesta sigue un patrón estricto. Durante una solicitud, las clases de middleware se ejecutan de arriba hacia abajo según se definen en MIDDLEWARE. Durante una respuesta, se ejecutan de abajo hacia arriba. Esta arquitectura de capas tipo cebolla significa que el primer middleware de la lista envuelve todo lo demás.
# 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 responseUna pregunta de seguimiento común: "¿Cómo se cortocircuita la cadena de middleware?" Devolver una HttpResponse desde __call__ antes de llamar a self.get_response(request) detiene la cadena por completo. Los middleware restantes y la vista nunca se ejecutan.
# middleware.py — Rate limiting con cortocircuito
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 y process_template_response
Más allá de __call__, el middleware de Django admite tres métodos hook opcionales. Los entrevistadores los utilizan para medir la profundidad del conocimiento.
# middleware.py — Middleware completo con todos los 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 se activa después de la resolución de URL pero antes de la vista. Devolver None continúa la ejecución; devolver una HttpResponse cortocircuita. process_exception se activa solo ante excepciones no controladas. process_template_response se activa solo para objetos TemplateResponse, no para HttpResponse regulares.
¿Listo para aprobar tus entrevistas de Django?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Preguntas de entrevista DRF: rendimiento de serializers
Las preguntas sobre serializers de Django REST Framework se centran en la serialización anidada y las implicaciones de rendimiento de los distintos enfoques. La pregunta más formulada: "¿Cómo se manejan las relaciones anidadas sin provocar 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"]El serializer por sí solo no resuelve el rendimiento. El ViewSet debe optimizar el 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")
)Sin select_related y prefetch_related en el ViewSet, cada desarrollador serializado dispara consultas individuales para su empresa y habilidades. En una lista de 50 desarrolladores, eso significa 1 + 50 + 50 = 101 consultas en lugar de 3.
Permisos y autenticación personalizados en DRF
Una pregunta frecuente en entrevistas sobre DRF: "Escriba un permiso personalizado que restrinja el acceso según el rol del usuario y el propietario del 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 ownerEl matiz que buscan los entrevistadores: has_permission se ejecuta en cada solicitud (nivel lista), mientras que has_object_permission se ejecuta solo cuando se llama a get_object() (nivel detalle). Olvidar sobrescribir get_queryset para las vistas de lista crea una brecha de seguridad donde los usuarios pueden ver objetos que no les pertenecen.
Depender únicamente de has_object_permission sin filtrar el queryset deja el endpoint de lista desprotegido. Siempre se debe combinar los permisos a nivel de objeto con un get_queryset filtrado para aplicar el control de acceso tanto en las vistas de lista como de detalle.
Throttling y patrones de paginación en DRF
El throttling y la paginación son preguntas de seguimiento estándar. Los entrevistadores quieren ver que el candidato comprende la configuración de API lista para producción.
# 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=abc123La paginación por cursor supera a la paginación por offset en conjuntos de datos grandes porque no necesita contar el número total de filas. La contrapartida: los clientes no pueden saltar a una página arbitraria. Esta es la respuesta esperada cuando los entrevistadores preguntan "¿Por qué elegirían paginación por cursor en lugar de paginación por número de página?"
Conclusión
Puntos clave para la preparación de entrevistas Django:
- Optimización del ORM: siempre asociar el método de consulta al tipo de relación.
select_relatedpara ForeignKey/OneToOne,prefetch_relatedpara ManyToMany y FK inversa. Los QuerySets personalizados permiten lógica de negocio encadenable y reutilizable. - Arquitectura de middleware: la solicitud fluye de arriba hacia abajo, la respuesta de abajo hacia arriba. Cortocircuitar devolviendo una respuesta antes de
get_response()es un patrón fundamental para rate limiting, verificaciones de autenticación y validación de solicitudes. - Rendimiento de serializers DRF: los serializers anidados requieren optimización explícita del queryset en el ViewSet. Sin
select_related/prefetch_related, la serialización provoca consultas N+1 a escala. - Permisos DRF: combinar
has_object_permissioncon unget_querysetfiltrado para aplicar control de acceso en endpoints de lista y detalle. Los permisos a nivel de objeto solos dejan las vistas de lista sin protección. - Throttling y paginación: la paginación por cursor escala mejor que el offset en tablas grandes. Configurar tasas de throttling separadas para usuarios anónimos y autenticados.
Para afianzar estos conocimientos, se recomienda practicar con preguntas de entrevista sobre el ORM de Django y preguntas sobre middleware Django en SharpSkill antes de la entrevista real.
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Etiquetas
Compartir
Artículos relacionados

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.

Django 6.0 en 2026: Claves Primarias Compuestas, Tareas en Segundo Plano y Preguntas de Entrevista Técnica
Guía completa de Django 6.0: claves primarias compuestas, tareas nativas en segundo plano, template partials, middleware CSP y preguntas de entrevista.

Django y Celery en 2026: Procesamiento Asíncrono y Preguntas de Entrevista
Guía completa de Django y Celery en 2026: configuración, colas, tareas periódicas, monitoreo con Flower, comparativa con Django 6.0 y preguntas de entrevista técnica.