Calcular campos dinámicos con SerializerMethodField

Resumen

Cuando trabajas con APIs en Django REST Framework, a veces necesitas mostrar un valor que no existe directamente en tu modelo, sino que se calcula a partir de otros campos. Aquí entra en juego SerializerMethodField, una herramienta que te permite agregar campos calculados sin modificar tu base de datos.

Qué es SerializerMethodField y para qué sirve

Imagina que tienes un modelo Patient con la fecha de nacimiento, pero en tu endpoint quieres mostrar la edad. No tiene sentido guardar la edad en la base de datos porque cambia cada año. La solución es calcularla al momento de serializar.

SerializerMethodField es un campo de solo lectura que ejecuta un método de tu clase serializer y retorna el valor calculado. Recibe la instancia del modelo y desde ahí puedes acceder a cualquier atributo para hacer la lógica que necesites [1:00].

¿Qué es SerializerMethodField en DRF? Es un campo de serializer que permite calcular y retornar valores dinámicos a partir de la instancia del modelo, sin necesidad de almacenarlos en la base de datos.

Cómo calcular la edad de un paciente desde la fecha de nacimiento

El objetivo es transformar un campo date_of_birth en un valor numérico que represente la edad del paciente. Para lograrlo, necesitas dos piezas: el módulo date de Python y un método dentro del serializer.

Cómo importar el módulo correcto en Python

La importación que necesitas es específica. Como el campo en el modelo es de tipo Date y no Datetime, importas solo date:

python from datetime import date

Con esto puedes usar date.today() para obtener la fecha actual y restar la fecha de nacimiento [2:30].

Cómo definir el campo age en el serializer

Dentro de tu clase serializer, declara el nuevo campo y crea el método correspondiente. Si dejas vacío el parámetro method_name, Django REST Framework genera el nombre automáticamente con el prefijo get_ seguido del nombre del campo.

python from rest_framework import serializers from datetime import date

class PatientSerializer(serializers.ModelSerializer): age = serializers.SerializerMethodField()

def get_age(self, obj): age_timedelta = date.today() - obj.date_of_birth return age_timedelta.days // 365 class Meta: model = Patient fields = ['id', 'name', 'date_of_birth', 'age']

El detalle clave está en age_timedelta.days. Cuando restas dos fechas obtienes un objeto timedelta, no un número. Para convertirlo en un valor numérico debes acceder al atributo days y dividirlo entre 365 [3:45].

Por qué no debes retornar texto desde una API REST

Es tentador devolver algo como "45 años" directamente desde el serializer usando un f-string. Técnicamente funciona, pero es mala práctica.

  • Las APIs deben retornar valores puros y consistentes.
  • El formato y los textos pertenecen al front-end.
  • Muchas aplicaciones manejan varios idiomas y necesitan adaptar el texto.
  • Mezclar lógica de presentación en el backend complica el mantenimiento.

Lo ideal es retornar el número y documentar la unidad: la edad va en años, la duración en minutos, el precio en centavos. El cliente decide cómo mostrarlo.

¿Por qué no devolver strings con formato desde el backend? Porque rompe la separación de responsabilidades. El backend entrega datos, el frontend decide cómo presentarlos según el idioma o el contexto del usuario.

Cuándo conviene usar SerializerMethodField en lugar de modificar el modelo

No todo cálculo merece una columna nueva en la base de datos. SerializerMethodField brilla cuando el valor depende del momento de la consulta o se deriva de datos ya existentes.

Úsalo cuando:

  • El valor cambia con el tiempo, como la edad o la antigüedad.
  • Es una combinación simple de campos que ya tienes.
  • Solo se necesita en la respuesta del endpoint, no para filtrar ni ordenar.
  • Quieres evitar migraciones innecesarias.

Si en cambio el valor se va a consultar con frecuencia, se usa para filtros o se calcula con lógica pesada, probablemente convenga guardarlo en el modelo o usar una property combinada con caché.

Reto: calcula la experiencia de un doctor

Ahora aplica lo aprendido. Crea un método dentro del serializer del modelo Doctor que calcule los años de experiencia basándose en la fecha en la que empezó a trabajar. La lógica es la misma que usaste con la edad del paciente: resta de fechas, acceso a days y división entre 365.

¿Cómo resolviste el reto? Comparte tu implementación en los comentarios y cuéntame si encontraste alguna variación interesante para manejar años bisiestos.