Resumen

Agendar citas en una API médica requiere precisión. Aquí verás cómo construir un endpoint anidado en Django Rest para crear y listar appointments desde el viewset de doctores, aplicando validación con serializer, filtros con el ORM y respuestas HTTP claras. La solución es segura, reusable y alineada con REST.

¿Cómo estructurar el endpoint anidado para appointments?

Un endpoint anidado aprovecha el recurso padre. En este caso, se cuelga de Doctors: el camino queda como /doctors/{id}/appointments/. Para lograrlo, se define una @action en el viewset del doctor con detail=True y métodos get y post. Además, se especifica serializer_class para mostrar los campos correctos en la interfaz navegable de Django Rest.

  • detail=True limita la acción al recurso doctor actual.
  • serializer_class evita que se muestren campos del doctor cuando se crea un appointment.
  • get debe listar appointments del doctor. post debe crearlos.
from rest_framework.decorators import action from rest_framework import status, viewsets from rest_framework.response import Response from bookings.serializers import AppointmentSerializer from bookings.models import Appointment class DoctorViewSet(viewsets.ModelViewSet): ... @action(detail=True, methods=['get', 'post'], serializer_class=AppointmentSerializer) def appointments(self, request, pk=None): doctor = self.get_object() if request.method.lower() == 'post': data = {**request.data, 'doctor': doctor.id} serializer = AppointmentSerializer(data=data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) appointments = Appointment.objects.filter(doctor=doctor) serializer = AppointmentSerializer(appointments, many=True) return Response(serializer.data)

¿Cómo crear una cita con post usando serializer y validación?

El objetivo es que el usuario no pueda manipular el doctor. Por eso, se inyecta el id del doctor desde la URL con self.get_object() y se construye un diccionario data que combina los datos del usuario con el doctor.id. Luego se instancia el serializer con data, se valida y se guarda.

  • self.get_object() obtiene el doctor según el pk de la URL.
  • request.method dirige el flujo entre post y get.
  • serializer.is_valid(raise_exception=True) aplica reglas de validación y devuelve errores claros.
  • serializer.save() persiste el appointment porque es un ModelSerializer.
  • Response(..., status=status.HTTP_201_CREATED) confirma creación.
doctor = self.get_object() if request.method.lower() == 'post': data = {**request.data, 'doctor': doctor.id} serializer = AppointmentSerializer(data=data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED)

Habilidades y conceptos en juego:

  • Seguridad por diseño: el doctor se toma de la URL, no del cuerpo del request.
  • Buenas prácticas REST: post crea, get lista.
  • Experiencia de desarrollo: el serializer_class en el decorador muestra el formulario correcto en la interfaz navegable.
  • Control de acceso: el endpoint requiere estar logueado.

¿Cómo listar las citas con get filtrando por doctor?

Para listar, se filtran los appointments por el doctor actual con el ORM de Django y se serializan con many=True. El estado por defecto es 200, por lo que no es necesario especificarlo.

  • Appointment.objects.filter(doctor=doctor) devuelve solo las citas del doctor.
  • many=True indica que se serializa una colección.
  • Response(serializer.data) retorna JSON listo para el cliente.
appointments = Appointment.objects.filter(doctor=doctor) serializer = AppointmentSerializer(appointments, many=True) return Response(serializer.data)

Keywords y datos importantes para fijar aprendizaje:

  • url del recurso: /doctors/{id}/appointments/.
  • acción anidada con @action(detail=True, methods=['get', 'post']).
  • uso de serializer_class=AppointmentSerializer en el decorador.
  • patrón de validación: is_valid(raise_exception=True).
  • creación con save() y confirmación HTTP_201_CREATED.
  • listado con many=True y ORM filtrando por doctor=doctor.
  • vista de detalle: la acción depende del doctor existente.
  • interfaz navegable: sin serializer_class se mostrarían campos del doctor por defecto.
  • control de sesión: acceso solo para usuarios autenticados.
  • acciones extra: ejemplo previo set_on_vacation en Doctors.

¿Tienes dudas o quieres extenderlo con borrar una cita en la misma acción? comenta cómo planeas manejar permisos y validaciones, y lo revisamos juntos.