Views
DRF ofrece varias capas de abstracción para escribir views. La clave está en entender cuándo usar cada una.
APIView — control total
APIView es la clase base de todas las vistas de DRF. Cada verbo HTTP es un método: get(), post(), put(), delete().
- Request/response a mano: sin queryset ni serializer automático
- Soporte de DRF incluido: parsing, autenticación, permisos, throttling
Usar cuando el endpoint no es CRUD de un modelo: procesar un pago, exportar un archivo, ejecutar una tarea.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class ProcesarPagoView(APIView):
def post(self, request):
monto = request.data.get("monto")
if not monto:
return Response(
{"error": "monto requerido"},
status=status.HTTP_400_BAD_REQUEST,
)
# lógica de negocio...
return Response({"ok": True}, status=status.HTTP_200_OK)
- Trade-off: Control absoluto, pero se escribe todo, incluso lo repetitivo
GenericAPIView — la base reutilizable
GenericAPIView es APIView con infraestructura para modelos y serializers: se declaran queryset y serializer_class, y la vista provee los métodos que los usan.
| Método | Qué hace |
|---|---|
get_queryset() |
Devuelve el queryset declarado |
get_serializer_class() |
Devuelve el serializer declarado |
get_object() |
Busca un objeto por pk dentro del queryset |
from rest_framework import generics
class ProductListView(generics.ListAPIView):
"""
ListAPIView ya trae ListModelMixin + GenericAPIView.
Solo definís queryset y serializer.
"""
queryset = Product.objects.all()
serializer_class = ProductSerializer
Vistas concretas incluidas: GenericAPIView + mixins ya combinados. Solo se definen queryset y serializer_class.
| Vista | Mixin que usa |
|---|---|
ListAPIView |
ListModelMixin |
CreateAPIView |
CreateModelMixin |
RetrieveAPIView |
RetrieveModelMixin |
UpdateAPIView |
UpdateModelMixin |
DestroyAPIView |
DestroyModelMixin |
ListCreateAPIView |
ListModelMixin + CreateModelMixin |
RetrieveUpdateDestroyAPIView |
RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin |
GenericAPIView sola no responde ningún verbo HTTP. Siempre se combina con mixins o vistas concretas.
Mixins — composición exacta
Un mixin implementa una única acción CRUD sobre los helpers de GenericAPIView. Para armar una vista se hereda GenericAPIView + los mixins de las acciones que se quieren exponer.
from rest_framework import mixins, generics
class ProductListCreateView(
mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView,
):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
| Mixin | HTTP | Acción |
|---|---|---|
ListModelMixin |
GET |
Listar colección |
CreateModelMixin |
POST |
Crear recurso |
RetrieveModelMixin |
GET |
Obtener un recurso |
UpdateModelMixin |
PUT / PATCH |
Actualizar recurso |
DestroyModelMixin |
DELETE |
Eliminar recurso |
- Trade-off: Más control que un ViewSet, pero más código boilerplate
Casos de uso
| Para… | Usar |
|---|---|
| Control total, lógica custom | APIView |
| CRUD de un modelo pero sin magia | GenericAPIView + mixins específicos |
| Solo list + retrieve (read-only) | GenericAPIView + ListModelMixin + RetrieveModelMixin |
| Un endpoint que no es CRUD | APIView directamente |
Buenas prácticas
| Práctica | Por qué |
|---|---|
Empezar con la vista concreta (ListAPIView) |
Si después se necesita más, se agregan mixins |
No temer bajar a APIView |
Forzar una vista genérica donde no va es peor |
perform_create() para lógica extra |
Más limpio que reescribir create() entero |
Resumen
APIView es la base. GenericAPIView ahorra el boilerplate de queryset/serializer. Los mixins permiten armar combinaciones exactas. Y las vistas concretas (ListAPIView, etc.) son el atajo para el 90% de los casos.