Resumen

Crear acciones en Django Rest Framework con seguridad y claridad mejora la experiencia de desarrollo y la de quienes consumen la API. Aquí verás cómo implementar acciones en un view set para gestionar estados como vacaciones, cómo asegurar endpoints idempotentes y cómo optimizar la URL con url_path para legibilidad y SEO.

¿Cómo crear acciones en Django Rest Framework con view sets?

Agregar acciones a recursos permite ejecutar comportamientos específicos sobre un ítem, como activar o desactivar un estado. En DRF se logra con el decorador @action dentro de un view set, definiendo los métodos permitidos y si actúa sobre detalle con detail=True.

  • Acciones: comportamientos sobre recursos como pagos o estados.
  • Decorador @action: añade rutas personalizadas al view set.
  • detail=True: la acción usa el ID del recurso en la URL.
  • methods=['post']: restringe la acción a POST.
  • get_object: recuperación segura del objeto actual en el view set.

¿Qué pasos aplicar en el modelo y migraciones?

Primero, añade el campo booleano en el modelo del doctor. Por defecto inicia en False.

# models.py
class Doctor(models.Model):
    # otros campos...
    is_on_vacation = models.BooleanField(default=False)

Crea y aplica migraciones.

python manage.py makemigrations
python manage.py migrate

¿Cómo definir una acción POST con detail true?

Usa @action para crear dos rutas: una para encender el estado y otra para apagarlo. Importa el decorador y la respuesta de DRF.

# views.py
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

class DoctorViewSet(ModelViewSet):
    queryset = Doctor.objects.all()

    @action(detail=True, methods=['post'], url_path='set-on-vacation')
    def set_on_vacation(self, request, pk=None):
        doctor = self.get_object()
        doctor.is_on_vacation = True
        doctor.save()
        return Response({'status': 'el doctor está en vacaciones'})

    @action(detail=True, methods=['post'], url_path='set-off-vacation')
    def set_off_vacation(self, request, pk=None):
        doctor = self.get_object()
        doctor.is_on_vacation = False
        doctor.save()
        return Response({'status': 'el doctor no está en vacaciones'})

Claves de esta implementación: - Self, request y pk: la acción recibe el contexto del view set y el ID del recurso. - get_object: reutiliza lógica de filtros y permisos del view set. - Response: siempre retorna contenido útil para el cliente.

¿Qué rol cumple get_object en la acción?

En lugar de consultar manualmente el queryset, self.get_object() obtiene el recurso actual aplicando filtros y validaciones del view set. Esto evita duplicar lógica y reduce errores al modificar código que ya funciona.

¿Por qué la idempotencia importa en endpoints REST?

Un endpoint debe permitir reintentos sin cambiar el resultado final si el mismo comando se repite. Por eso, en vez de un "toggle" que alterna valores con cada request, conviene implementar acciones explícitas: “encender” y “apagar”.

  • Idempotencia: repetir requests no altera el estado final.
  • Evita confusiones: un “toggle” puede dejar el estado inesperado si hay reintentos tras fallos.
  • Diseño claro: acciones como set-on y set-off comunican intención.

Ejemplo no recomendado por no ser idempotente:

@action(detail=True, methods=['post'])
def toggle_vacation(self, request, pk=None):
    doctor = self.get_object()
    doctor.is_on_vacation = not doctor.is_on_vacation
    doctor.save()
    return Response({'status': 'actualizado'})

¿Cómo optimizar las URLs de acciones para SEO y legibilidad?

DRF genera la ruta de la acción a partir del nombre del método, lo que suele crear rutas con guiones bajos. Para mejorar legibilidad y SEO, define la ruta con url_path usando guiones.

  • url_path: establece la ruta pública de la acción.
  • kebab-case: preferible a snake_case en URLs.
  • Consistencia: facilita el consumo y la documentación.

Ejemplo con guiones:

@action(detail=True, methods=['post'], url_path='set-on-vacation')
def set_on_vacation(self, request, pk=None):
    # implementación...
    pass

¿Listo para practicar? Implementa en el view set de pacientes una acción que devuelva el reporte de la historia clínica en JSON vía POST. ¿Cómo mostrarías el texto en formato JSON y qué clave usarías en la respuesta? Comparte tu enfoque en los comentarios.