Contenido del curso
Parámetros y Validación
CRUD en FastAPI
Arquitectura en FastAPI
Bases de Datos y Consultas
Middlewares
Unit Testing
Seguridad y Autenticación
Filtros con Enum y Query params en FastAPI
Resumen
Filtrar registros por estado es una de esas tareas que parecen simples hasta que te toca implementarlas bien. Con SQLModel y FastAPI puedes usar Enums y query params para construir endpoints que filtren datos de forma limpia, tipada y segura, ideal para escenarios como suscripciones activas e inactivas en una API real.
Por qué agregar un campo status con Enum al modelo CustomerPlan
Cuando un cliente puede activar y desactivar planes varias veces, necesitas distinguir cuáles están vigentes. Ahí entra el campo status.
En lugar de aceptar cualquier texto, restringes los valores posibles con un Enum. Un Enum es una clase que define una lista cerrada de valores permitidos, y en Python la creas heredando del módulo enum.
python from enum import Enum
class StatusEnum(str, Enum): active = "active" inactive = "inactive"
Nota el truco: heredar de str además de Enum permite que el valor se serialice como texto plano, algo que FastAPI y la base de datos van a agradecer. Luego añades el campo al modelo con un valor por defecto:
python status: StatusEnum = Field(default=StatusEnum.active)
Como cambiaste la estructura, regenera la base de datos borrándola y reiniciando la aplicación para que el nuevo campo se cree.
¿Qué es un Enum en Python? Es una clase que define un conjunto fijo de valores posibles. Sirve para evitar errores como escribir "activo", "Active" o "ACTIVO" en distintos lugares del código.
Cómo usar Query params en FastAPI para recibir el estado del plan
Los query params son esos valores que viajan en la URL después del signo ?, como en /customers/1/plans?plan_status=active. FastAPI los maneja con la clase Query, que importas directamente desde el framework.
En el endpoint de suscripción a un plan agregas la variable al final de los parámetros, porque tiene un valor por defecto:
python from fastapi import Query
plan_status: StatusEnum = Query(default=StatusEnum.active)
Fíjate que el parámetro se llama plan_status y no status para evitar clash con la clase StatusEnum ya importada. Pequeño detalle, gran ahorro de bugs.
Después pasas ese valor al crear el CustomerPlan:
python customer_plan = CustomerPlan( plan_id=plan_id, customer_id=customer_id, status=plan_status )
Cuando pruebas el endpoint en la documentación interactiva, vas a ver un dropdown con las opciones active e inactive, y active preseleccionado. Justo lo que querías.
Cómo filtrar registros con session.exec, select y múltiples where
Ahora viene la parte interesante: usar ese mismo plan_status para filtrar la lista de planes de un cliente. El endpoint que devuelve los planes de un customer necesita una query personalizada porque obtener el cliente no basta para filtrar sus planes por estado.
La solución es construir un select con dos condiciones encadenadas:
python query = select(CustomerPlan).where( CustomerPlan.customer_id == customer_id ).where( CustomerPlan.status == plan_status ) plans = session.exec(query).all() return plans
Desglosando lo que hace cada pieza:
select(CustomerPlan): indica qué tabla quieres consultar.- Primer
where: filtra por el cliente específico. - Segundo
where: filtra por el estado recibido en la URL. session.exec(query): ejecuta la consulta en la base de datos..all(): obtiene todos los resultados como lista.
El resultado lo guardas en plans y reemplazas el antiguo customer_db que devolvías antes. Ya no devuelves al cliente con sus planes anidados, devuelves la lista filtrada directamente.
¿Para qué sirve session.exec en SQLModel? Es el método que ejecuta una query construida con
selectcontra la base de datos. Lo combinas con.all(),.first()o.one()según cuántos resultados esperes.
Qué ganas al combinar Enums, Query y SQLModel
Esta combinación te da tres beneficios concretos que vale la pena tener claros:
- Validación automática: si alguien envía
?plan_status=pending, FastAPI rechaza la petición antes de que llegue a tu lógica. - Documentación interactiva: Swagger muestra los valores disponibles como un dropdown, sin que escribas documentación extra.
- Consultas tipadas: el editor te autocompleta y te avisa si comparas tipos incompatibles en los
where.
Un ejemplo concreto: si un cliente tuvo tres planes a lo largo del tiempo y solo uno sigue activo, una petición a /customers/1/plans?plan_status=active te devuelve únicamente ese registro, sin que tengas que filtrar manualmente en código.
Cómo extender el filtro para aceptar múltiples estados
El reto que te queda es ampliar el endpoint para aceptar más de un estado en la misma request. Piensa en una petición como ?plan_status=active&plan_status=inactive que devuelva ambos tipos de planes.
Para lograrlo, cambia el tipo del parámetro a una lista de StatusEnum y usa el operador in_ de SQLAlchemy en el where. Algo como:
python plan_status: list[StatusEnum] = Query(default=[StatusEnum.active])
Y en la query:
python .where(CustomerPlan.status.in_(plan_status))
Crea datos de prueba con planes en distintos estados, prueba el filtro y cuéntame en los comentarios cómo te funcionó tu implementación.