Potencia tus endpoints de Django REST con serializadores anidados: agrega información relacionada en un solo response sin duplicar lógica ni romper contratos. Aquí verás cómo añadir las citas médicas de un paciente dentro del recurso Patient usando un serializer anidado, con parámetros clave como many y read_only para mantener un diseño limpio, seguro y flexible.
¿Qué son los serializadores anidados y por qué mejoran el response?
Los serializadores anidados permiten incluir un campo cuyo valor proviene de otro serializer. Así, un recurso como Patient puede exponer una lista de citas usando el serializer de Appointment. Esto hace más claro el consumo de la API y estandariza la salida.
- Centralizan la lógica de representación en un lugar.
- Escalan cambios: modificas un serializer y se reflejan en todos los response.
- Representan relaciones entre modelos de forma eficiente.
En este caso, se agrega el campo appointments al serializer de Patient para listar todas las citas del paciente mediante un serializer existente de Appointments.
¿Cómo implementar el campo appointments en Patient serializer?
Primero, ubica el serializer de paciente y garantiza que la Meta tenga los fields que deseas exponer. Luego, importa el serializer de citas y define el campo anidado con los parámetros correctos.
- Importa el serializer de Appointment desde la app de reservas.
- Declara el campo anidado en Patient con many=True y read_only=True.
- Incluye "appointments" en la lista de fields para que aparezca en el response.
- No olvides el id: aunque el modelo lo crea automáticamente, debes listarlo en fields si quieres verlo en la salida.
Ejemplo de estructura mínima:
# patients/serializers.py
from rest_framework import serializers
from patients.models import Patient
from bookings.serializers import AppointmentSerializer
class PatientSerializer(serializers.ModelSerializer):
appointments = AppointmentSerializer(many=True, read_only=True)
class Meta:
model = Patient
fields = [
'id', # importante incluirlo para verlo en la salida
# ... otros campos del modelo Patient
'appointments', # el nuevo campo anidado
]
Claves del diseño:
- many=True: indica que es una lista de objetos relacionados.
- read_only=True: evita que alguien intente enviar citas por este endpoint; la creación/edición de citas ocurre en su propio endpoint.
¿Cómo validar en la API y cargar datos de prueba con shell?
Tras definir el campo, verifica que la API muestre el nuevo JSON enriquecido y, si está vacío, crea una cita de ejemplo desde shell.
¿Cómo ver el nuevo campo en la lista y el detalle?
- Ejecuta el servidor:
python manage.py runserver.
- Abre el listado:
/api/patients/.
- Confirma que aparezca appointments como una lista.
- Si no ves el id, agrégalo en fields y recarga.
- Abre el detalle del paciente (por ejemplo, con id 3) y verifica que appointments sea una lista, inicialmente vacía.
¿Cómo crear una appointment de ejemplo en shell?
Desde shell, crea datos mínimos para observar la estructura anidada en el response.
# Abrir shell
authenticate = False # si aplica en tu entorno, caso de ejemplo
from datetime import date, time
from doctors.models import Doctor
from patients.models import Patient
from bookings.models import Appointment
patient = Patient.objects.get(id=3)
doctor = Doctor.objects.first()
Appointment.objects.create(
patient=patient,
doctor=doctor,
date=date(2024, 5, 20), # ejemplo de fecha
time=time(9, 30), # ejemplo de hora
notes='Control general.', # opcional
status='scheduled' # opcional, según tu modelo
)
Al recargar el detalle del paciente, verás appointments como una lista de objetos, cada uno serializado por el serializer de Appointment. Esto ofrece más flexibilidad al cliente sin cambiar de endpoint ni mezclar responsabilidades.
¿Te gustaría ver un ejemplo análogo para Doctor con su lista de citas? Comenta cómo estructurarías ese serializer y qué campos incluirías en el response.