Querysets Dinámicos10 temas

Querysets Dinámicos

En DRF, get_queryset() es un método disponible en vistas genéricas (como ListAPIView) que permite definir el queryset dinámicamente según el contexto de cada request. En lugar de devolver siempre los mismos datos, se puede adaptar la consulta basándose en el usuario autenticado, query params, o cualquier otra información disponible.

¿Por qué usarlo?

  • Filtrado seguro: Cada usuario ve solo los datos que le corresponden; el filtro se aplica del lado del servidor.
  • Performance: Filtrar en la base de datos, no en Python, evita cargar en memoria objetos innecesarios.
  • Flexibilidad: El queryset se adapta a cada request: un admin ve todos los registros, un usuario regular solo los propios.

Regla de oro: Cualquier filtro de seguridad o aislamiento de datos va siempre en get_queryset(); nunca confiar en que el cliente filtre desde el frontend.

Código de ejemplo

Una aplicación donde cada usuario tiene recursos propios (posts, órdenes, documentos, etc.). Con get_queryset() se garantiza que cada quien vea solo lo suyo:

from rest_framework import generics
from rest_framework.permissions import IsAuthenticated


class MyResourceListView(generics.ListAPIView):
    """
    Cada usuario ve únicamente los recursos que le pertenecen.
    """
    serializer_class = ResourceSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        """
        Filtra automáticamente por el usuario autenticado.
        No importa qué parámetros mande el cliente, este filtro
        se aplica SIEMPRE.
        """
        return Resource.objects.filter(owner=self.request.user)

También se pueden combinar filtros dinámicos con condiciones:

def get_queryset(self):
    user = self.request.user
    qs = Resource.objects.all()

    # Filtro base de seguridad
    if not user.is_staff:
        qs = qs.filter(owner=user)

    # Filtros adicionales según query params
    status = self.request.query_params.get('status')
    if status:
        qs = qs.filter(status=status)

    return qs.order_by('-created_at')

Buenas prácticas

Práctica Por qué
Usar select_related / prefetch_related Evita consultas N+1 cuando se accede a relaciones
Mantener get_queryset() enfocado Si la lógica crece demasiado, moverla a un QuerySet personalizado del modelo
Aplicar filtros de seguridad primero Los filtros obligatorios van en get_queryset(); los opcionales (búsqueda, orden) van con django-filter
No repetir lógica Si varios views comparten el mismo filtro base, crear un mixin o una clase base

Recursos

DRF Docs: Generic Views