Django Rest Framework: de funciones a vistas genéricas
Resumen
Organiza y escala tus endpoints en Django Rest Framework con un refactor claro: pasa de vistas basadas en funciones a vistas basadas en clases (APIView) y luego simplifica con vistas genéricas como ListApiView y CreateApiView. Verás cómo el código se vuelve más limpio, reutilizable y fácil de mantener sin perder control.
¿Por qué migrar de funciones a vistas basadas en clases en Django Rest Framework?
Las vistas basadas en clases permiten agrupar lógica por método HTTP y aprovechar funcionalidades nativas de DRF. Además, simplifican la configuración de métodos permitidos, permisos y throttle, y añaden soporte automático a HEAD y OPTIONS.
Estructura clara: métodos get, post, put, delete separados por función.
Escalabilidad real: reutilización con herencia y clases padre.
Validación automática:allowed methods limita respuestas a los métodos definidos.
Más herramientas listas: permisos y throttle disponibles cuando se necesiten.
Mejor experiencia de cliente:HEAD obtiene solo headers rápidamente. OPTIONS informa campos y métodos disponibles.
¿Cómo refactorizar ApiView a clases en DRF?
Primero, importa la clase y crea tu vista basada en clases. Luego define los métodos HTTP y conecta la URL con as_view.
¿Cómo declarar la clase y métodos get/post?
from rest_framework.views import ApiView
classListPatientsView(ApiView): allowed_methods =['GET','POST']defget(self, request):# Copia la lógica de listado que usabas en la vista basada en función.passdefpost(self, request):# Copia la lógica de creación del recurso patient.pass
Idea clave:allowed methods valida qué métodos responderán.
Beneficio: el recurso lista queda expresivo: GET lista, POST crea.
La interfaz navegable de DRF mostrará además HEAD y OPTIONS automáticamente.
¿Cómo convertir el detalle con get/put/delete?
from rest_framework.views import ApiView
classDetailPatientView(ApiView): allowed_methods =['GET','PUT','DELETE']defget(self, request, pk):# Recupera y retorna el paciente por pk.passdefput(self, request, pk):# Actualiza el paciente por pk.passdefdelete(self, request, pk):# Elimina el paciente por pk.pass
Al refactorizar notarás duplicación de consultas para obtener el objeto.
Señal de mejora: extraer una función auxiliar o pasar a vistas genéricas.
¿Qué simplifican las vistas genéricas ListApiView y CreateApiView?
Las vistas genéricas ya traen implementados los métodos estándar de REST. Solo defines serializerClass y QuerySet, y DRF se encarga del resto. Así reduces tu vista de lista y creación a pocas líneas.
serializerClass: indica cómo serializar y validar los datos.
QuerySet: especifica de dónde obtener los elementos a listar o crear.
Efecto inmediato: puedes borrar el get y el post manuales.
Además, en la interfaz navegable puedes alternar entre HTML form y raw data para enviar JSON; DRF incluso muestra un datetime picker para fechas. Si más adelante necesitas personalizar comportamiento, ya sabes qué método sobrescribir porque entendiste el flujo manual primero.
Habilidades prácticas: refactor paso a paso, herencia múltiple de vistas genéricas, eliminación de duplicación, uso de la interfaz navegable para probar endpoints.
¿Te animas a dar el siguiente paso? Implementa el detalle con vistas genéricas y comparte tu código en comentarios para recibir feedback.
Gracias por tu comentario! Espero que estés disfrutando el curso
Un aspecto clave de Django Rest Framework es que ofrece herramientas muy útiles que simplifican el desarrollo. A diferencia de otros frameworks donde es necesario implementar muchas funcionalidades manualmente, DRF te permite optar entre hacerlo a mano o aprovechar sus características integradas. Esto facilita la creación de aplicaciones completamente personalizadas y flexibles, adaptadas a las necesidades específicas del proyecto 🐍.
:o
Funciona solo haciendo esto...
Es increible que hasta el pk es abstraido...... Osea, si lees este código es casi imposible, sin saber lo que pasa por debajo, que esta vista hace get/put/delete sobre un id.
Sí, viendo la definición de la clase tienen como "pk" el nombre del atributo para el id. Imagino por eso nos enseñaron a usar pk para el id en la url
Profe, realicé el cambio de las vistas basadas en funciones con la clase APIView, sin embargo, no me aparece por defecto los métodos HEAD y OPTIONS, ni siquiera el HTML form, sabes qué podría ser? O alguien más sabe qué puede ser?
estoy con la misma duda
juan jose, al seguir el curso, cuando se utilizan los ViewSets se arregla el problema
Lo mas que pude simplificarlo fue en el siguiente codigo, use la clase RetrieveUpdateDestroyView ya que puede hacer ambas operaciones update y delete sin necesidad de especificar el allowed_methods
Excelente! muy simple y útil saber como funciona!
Increíble la simplificación que se realiza
Dejo un resumen, breve, de HEAD y OPTIONS:
HEAD: Se utiliza cuando solo necesitas los headers de una solicitud, sin el cuerpo (por ejemplo, para verificar la existencia o propiedades de un recurso).
OPTIONS: Te dice qué métodos HTTP son soportados por un recurso, útil para seguridad y manejo de políticas entre dominios (CORS).
La simplificación del código realmente me impresiono.😎
Es muy util ademas para evitar bugs al escribir menos codigo.
Un endpoint es una URL específica que permite la interacción entre un cliente y un servidor en una API (Interfaz de Programación de Aplicaciones). En el contexto de Django REST Framework, un endpoint define cómo se pueden acceder a los recursos a través de métodos HTTP como GET, POST, PUT o DELETE. Cada endpoint se asocia a una vista que maneja las solicitudes y respuestas, facilitando la comunicación y el intercambio de datos en aplicaciones web.
En Django REST Framework, las vistas basadas en funciones (FBV) son útiles cuando se necesita algo rápido, simple y directo. Se suelen usar para endpoints muy básicos que solo manejan una o dos operaciones, como un GET de prueba o un endpoint de estado. Son fáciles de entender y escribir, por lo que resultan convenientes en prototipos pequeños o cuando la lógica no va a crecer demasiado.
Por otro lado, las vistas basadas en clases (CBV) ofrecen una estructura más organizada y sobre todo escalable. Gracias a la herencia, los mixins y los viewsets, no solo permiten manejar los métodos principales (get, post, put, delete), sino que también facilitan la creación de funciones personalizadas dentro de la misma clase, algo que en FBV sería más engorroso de mantener. Esta capacidad de extender y reutilizar código hace que las CBV sean la mejor opción para proyectos grandes o APIs que evolucionan con nuevas funcionalidades.
Para los que tuvieron problemas vamos a dividir los problemas en dos partes primero porque no aparecen todo los metodos:
El atributo allowed_methods describe los métodos que puede utilizar ese endpoint en concreto, como solo colocaste GET y POST, sobreescribiste los otros métodos por default que tiene esta vista, esto lo puedes comprobar comentando esa línea o añadiendo HEAD y OPTIONS al array de allowed_methods.
Para la segunda Parte sobre el motivo por el cual no te aparece la forma HTML en el propio endpoint cuando utilizas la vista basada en APIView es porque Django REST Framework no renderiza automáticamente formularios HTML para vistas basadas en clases genéricas como APIView o para métodos explícitos como get y post. Los formularios de la interfaz de navegación del API están disponibles únicamente cuando usas las vistas genéricas de DRF (CreateAPIView, DestroyAPIView, ListAPIView, etc.) o que utilizan el decorador @api_view, que está diseñado para manejar vistas basadas en funciones
Con respecto al reto, mi vista quedaría de la siguiente manera:
# Define the ListPatientsView class with allowed_methods restrictionclassListPatientsView(APIView): allowed_methods =['GET','POST']# Only allow GET and POST methods# GET method to list all patientsdefget(self, request): patients = Patient.objects.all()# Retrieve all patients serializer = PatientSerializer(patients, many=True)# Serialize the datareturn Response(serializer.data)# Return the serialized data in the response# POST method to create a new patientdefpost(self, request): serializer = PatientSerializer(data=request.data)# Deserialize the request data serializer.is_valid(raise_exception=True)# Automatically handle validation exceptions serializer.save()# Save the new patientreturn Response(status=status.HTTP_201_CREATED)# Respond with 201 Created without returning the patient data
Han actualizado los métodos: ahora en vez de allowed_methods, se usa http_method_names, eso si, DRF es lo suficientemente inteligente: si se escribe el método def get(self, request):, DRF automáticamente sabrá que el único método permitido es GET. Si alguien intenta mandar un POST, responderá de inmediato con un error 405 Method Not Allowed sin que tú tengas que bloquearlo manualmente.
Al cambiar a vista basada en Clases, no me está mostrando ni el form, ni el json preescrito, ni el HEAD, ni el OPTIONS. ¿Qué sucede ahí?
Compartenos el código para poder ayudarte por favor
Si no estoy mal, se resolvió cuando dejé de usar la APIView y usé las de generics, creo que así fue que apareció todo lo que dije y el form en las 2 versiones: raw(json) y html. Pero en el video, te aparecen sin todavía haber usado las de generics.
Esta es la forma en la cual creemos que se podía optimizar.
Me gustaria saber porque en python es común crear las clases en un solo archivo y no cada clase en cada archivo?
Podria decir que son gustos, también es posible crear un archivo por class
Las vistas basadas en funciones (FBV) y las vistas basadas en clases (CBV) en Django REST Framework tienen diferencias clave:
Estructura: FBV utiliza funciones simples para manejar las peticiones, mientras que CBV utiliza clases, lo que permite una organización mejorada y reutilización de código.
Escalabilidad: CBV es más escalable, ya que permite la adición de nuevas funcionalidades (métodos) mediante la extensión de la clase, mientras que FBV puede volverse más difícil de manejar a medida que crece la lógica.
Estandarización: CBV ofrece vistas genéricas que simplifican tareas comunes (como listar y crear), mientras que FBV requiere más código repetido para cada funcionalidad.
Utilizar CBV puede mejorar la mantenibilidad de tu código a largo plazo.