FastAPI es un web framework rápido y ligero para construir modernas interfaces de programación de aplicaciones utilizando Python 3.6 y  versiones superiores. En este tutorial, repasaremos los fundamentos de la construcción de una aplicación con FastAPI, y podrás hacerte una idea de por qué ha sido nominado como uno de los mejores frameworks de código abierto de 2021.

Una vez que estés preparado para desarrollar tus propias aplicaciones FastAPI, no tendrás que buscar mucho para encontrar un lugar donde alojarlas. Los servicios de Alojamiento de Aplicaciones y Alojamiento de Bases de Datos de Kinsta proporcionan una Plataforma como Servicio que es fuerte en Python.

Primero aprendamos lo básico.

Ventajas de FastAPI

A continuación se exponen algunas de las ventajas que el framework FastAPI FastAPI aporta a un proyecto.

  • La velocidad: Como su nombre indica, FastAPI es un framework muy rápido. Su velocidad es comparable a la de Go y Node.js, que generalmente se consideran entre las opciones más rápidas para construir APIs.
  • Fácil de aprender y codificar: FastAPI ya ha resuelto casi todo lo que necesitarás para crear una API lista para la producción. Como desarrollador que utiliza FastAPI, no necesitas codificar todo desde cero. Con sólo unas pocas líneas de código, puedes tener una API RESTful lista para su despliegue.
  • Documentación exhaustiva: FastAPI utiliza los estándares de documentación de OpenAPI, por lo que la documentación puede generarse dinámicamente. Esta documentación proporciona información detallada sobre los puntos finales, las respuestas, los parámetros y los códigos de retorno de FastAPI.
  • API con menos errores: FastAPI admite la validación de datos personalizada, lo que permite a los desarrolladores construir APIs con menos errores. Los desarrolladores de FastAPI se jactan de que el marco de trabajo da lugar a menos errores inducidos por el ser humano, hasta un 40% menos.
  • Type hints: El módulo de tipos se introdujo en Python 3.5. Esto te permite declarar el type de una variable. Cuando se declara el tipo de una variable, los IDE son capaces de proporcionar un mejor soporte y predecir los errores con mayor precisión.

Cómo Empezar con FastAPI

Para seguir este tutorial y empezar a utilizar FastAPI, tendrás que hacer primero algunas cosas.

Asegúrate de que tienes un editor de texto/IDE de programador, como Visual Studio Code. Otras opciones son Sublime Text y Espresso.

Es una práctica habitual tener tus aplicaciones de Python y sus instancias funcionando en entornos virtuales. Los entornos virtuales permiten que se ejecuten simultáneamente diferentes conjuntos de paquetes y configuraciones, y evitan conflictos debidos a versiones de paquetes incompatibles.

Para crear un entorno virtual, abre tu terminal y ejecuta este comando

$ python3 -m venv env

También tendrás que activar el entorno virtual. El comando para hacerlo variará en función del sistema operativo y del shell que estés utilizando. Aquí tienes algunos ejemplos de activación CLI para varios entornos:

# On Unix or MacOS (bash shell): 
/path/to/venv/bin/activate

# On Unix or MacOS (csh shell):
/path/to/venv/bin/activate.csh

# On Unix or MacOS (fish shell):
/path/to/venv/bin/activate.fish

# On Windows (command prompt):
pathtovenvScriptsactivate.bat

# On Windows (PowerShell):
pathtovenvScriptsActivate.ps1

(Algunos IDEs compatibles con Python también pueden configurarse para activar el entorno virtual actual.)

Ahora, instala FastAPI:

$ pip3 install fastapi

FastAPI es un marco para construir APIs, pero para probar tus APIs necesitarás un servidor web local. Uvicorn es un servidor web de interfaz de puerta de enlace de servidor asíncrono (ASGI) para Python, muy rápido, que es ideal para el desarrollo. Para instalar Uvicorn, ejecuta este comando:

$ pip3 install "uvicorn[standard]"

Tras la instalación, crea un archivo llamado main.py en el directorio de trabajo de tu proyecto. Este archivo será el punto de entrada de tu aplicación.

Vista de un proyecto FastAPI básico dentro de un IDE.
Vista de un proyecto FastAPI básico dentro de un IDE.

Un Ejemplo Rápido de FastAPI

Para probar tu instalación de FastAPI, configura rápidamente un endpoint de ejemplo. En tu archivo main.py, pega el siguiente código y guarda el archivo:

# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
 return {"greeting":"Hello world"}

El fragmento anterior crea un endpoint FastAPI básico. A continuación te mostramos un resumen de lo que hace cada línea:

  • from fastapi import FastAPI: La funcionalidad de tu API la proporciona la clase FastAPI de Python.
  • app = FastAPI(): Esto crea una instancia de FastAPI.
  • @app.get("/"): Se trata de un decorador python que especifica a FastAPI que la función que hay debajo es la encargada de gestionar las peticiones.
  • @app.get("/"): Este es un decorador que especifica la ruta. Esto crea un método GET en la ruta del sitio. El resultado es devuelto por la función envuelta.
  • Otras posibles operaciones que se utilizan para comunicarse son @app.post(), @app.put(), @app.delete(), @app.options(), @app.head(), @app.patch() y @app.trace().

En el directorio de archivos, ejecuta el siguiente comando en tu terminal para iniciar el servidor API:

$ uvicorn main:app --reload

En este comando, main es el nombre de tu módulo. El objeto app es una instancia de tu aplicación, y se importa en el servidor ASGI. La bandera --reload indica al servidor que se recargue automáticamente cuando hagas algún cambio.

Deberías ver algo así en tu terminal:

 $ uvicorn main:app --reload
INFO: Will watch for changes in these directories: ['D:\WEB DEV\Eunit\Tests\fast-api']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [26888] using WatchFiles
INFO: Started server process [14956]
INFO: Waiting for application startup.
INFO: Application startup complete.

En tu navegador, navega hasta http://localhost:8000 para confirmar que tu API está funcionando. Deberías ver «Hello»: «World» como objeto JSON en la página. Esto ilustra lo fácil que es crear una API con FastAPI. Lo único que has tenido que hacer es definir una ruta y devolver tu diccionario Python, como se ve en la línea seis del fragmento anterior.

Aplicación FastAPI Hello World en un navegador web.
Aplicación FastAPI Hello World en un navegador web.

Utiliza Type Hints

Si utilizas Python, estás acostumbrado a anotar variables con tipos de datos básicos como int, str, float y bool. Sin embargo, a partir de la versión 3.9 de Python, se introdujeron estructuras de datos avanzadas. Esto te permite trabajar con estructuras de datos como dictionaries, tuples, y lists. Con los type hints de FastAPI, puedes estructurar el esquema de tus datos utilizando modelos pydánticos y luego, utilizar los modelos pydánticos para hacer sugerencias de tipo y beneficiarte de la validación de datos que se proporciona.

En el siguiente ejemplo, se demuestra el uso de type hints en Python con una sencilla calculadora de precios de comidas, calculate_meal_fee:

def calculate_meal_fee(beef_price: int, meal_price: int) -> int:
 total_price: int = beef_price + meal_price
 return total_price
print("Calculated meal fee", calculate_meal_fee(75, 19))

Ten en cuenta que los type hints no cambian la forma en que se ejecuta tu código.

Documentación Interactiva de la API de FastAPI

FastAPI utiliza Swagger UI para proporcionar documentación interactiva automática de la API. Para acceder a ella, navega a http://localhost:8000/docs y verás una pantalla con todos tus endpoints, métodos y esquemas.

Documentación de Swagger UI para FastAPI.
Documentación de Swagger UI para FastAPI.

Esta documentación automática de la API basada en el navegador la proporciona FastAPI, y no necesitas hacer nada más para aprovecharla.

Una documentación alternativa de la API basada en el navegador, también proporcionada por FastAPI, es Redoc. Para acceder a Redoc, navega a http://localhost:8000/redoc, donde se te presentará una lista de tus puntos finales, los métodos y sus respectivas respuestas.

Documentación de Redoc para FastAPI.
Documentación de Redoc para FastAPI.

Configurar Rutas en FastAPI

El decorador @app te permite especificar el método de la ruta, como @app.get o @app.post, y admite GET, POST, PUT y DELETE, así como las opciones menos comunes, HEAD, PATCH y TRACE.

Construye Tu Aplicación con FastAPI

En este tutorial, te guiaremos en la construcción de una aplicación CRUD con FastAPI. La aplicación podrá:

  • Crear un usuario
  • Leer el registro de un usuario en la base de datos
  • Actualizar un usuario existente
  • Eliminar un usuario concreto

Para ejecutar estas operaciones CRUD, crearás métodos que expongan los endpoints de la API. El resultado será una base de datos en memoria que puede almacenar una lista de usuarios.

Estructura de la tabla de la base de datos para los ejemplos de CRUD.
Estructura de la tabla de la base de datos para los ejemplos de CRUD.

Utilizarás la biblioteca pydantic para realizar la validación de los datos y la gestión de la configuración mediante anotaciones de tipo en Python. A efectos de este tutorial, declararás la forma de tus datos como clases con atributos.

Este tutorial utilizará la base de datos en memoria. Esto es para iniciarte rápidamente en el uso de FastAPI para construir tus APIs. Sin embargo, para la versión en vivo, puedes utilizar cualquier base de datos que elijas, como PostgreSQL, MySQL, SQLite o incluso Oracle.

Construir la Aplicación

Comenzarás creando tu modelo de usuario. El modelo de usuario tendrá los siguientes atributos:

  • id: Un identificador único universal (UUID)
  • first_name: El nombre del usuario
  • last_name: El apellido del usuario
  • gender: El género del usuario
  • rolesque es una lista que contiene los roles admin y user

Empieza creando un nuevo archivo llamado models.py en tu directorio de trabajo, y luego pega el siguiente código en models.py para crear tu modelo:


# models.py
from typing import List, Optional
from uuid import UUID, uuid4
from pydantic import BaseModel
from enum import Enum
from pydantic import BaseModel
class Gender(str, Enum):
 male = "male"
 female = "female"
class Role(str, Enum):
 admin = "admin"
 user = "user"
class User(BaseModel):
 id: Optional[UUID] = uuid4()
 first_name: str
 last_name: str
 gender: Gender
 roles: List[Role]

En el código anterior

  • Tu clase User extiende BaseModel, que a su vez se importa de pydantic.
  • Has definido los atributos del usuario, como se ha comentado anteriormente.

El siguiente paso es crear tu base de datos. Sustituye el contenido de tu archivo main.py por el siguiente código:


# main.py
from typing import List
from uuid import uuid4
from fastapi import FastAPI
from models import Gender, Role, User
app = FastAPI()
db: List[User] = [
 User(
 id=uuid4(),
 first_name="John",
 last_name="Doe",
 gender=Gender.male,
 roles=[Role.user],
 ),
 User(
 id=uuid4(),
 first_name="Jane",
 last_name="Doe",
 gender=Gender.female,
 roles=[Role.user],
 ),
 User(
 id=uuid4(),
 first_name="James",
 last_name="Gabriel",
 gender=Gender.male,
 roles=[Role.user],
 ),
 User(
 id=uuid4(),
 first_name="Eunit",
 last_name="Eunit",
 gender=Gender.male,
 roles=[Role.admin, Role.user],
 ),
]

En main.py:

  • Has inicializado db con un tipo List, y has pasado el modelo User
  • Creaste una base de datos en memoria con cuatro usuarios, cada uno con los atributos necesarios como first_name, last_name, gender, y roles. Al usuario Eunit se le asignan los roles de admin y user, mientras que a los otros tres usuarios sólo se les asigna el rol de user.

Leer Registros de la Base de Datos

Has configurado con éxito tu base de datos en memoria y la has llenado de usuarios, así que el siguiente paso es configurar un punto final que devuelva una lista de todos los usuarios. Aquí es donde entra FastAPI.

En tu archivo main.py, pega el siguiente código justo debajo de tu punto final Hello World:


# main.py
 @app.get("/api/v1/users")
 async def get_users():
 return db

Este código define el punto final /api/v1/users, y crea una función asíncrona, get_users, que devuelve todo el contenido de la base de datos, db.

Guarda tu archivo y podrás probar tu endpoint de usuario. Ejecuta el siguiente comando en tu terminal para iniciar el servidor API:

$ uvicorn main:app --reload

En tu navegador, navega hasta http://localhost:8000/api/v1/users. Esto debería devolver una lista de todos tus usuarios, como se ve a continuación:

Datos de usuarios recuperados por la solicitud de lectura de la base de datos FastAPI.
Datos de usuarios recuperados por la solicitud de lectura de la base de datos FastAPI.

En esta fase, tu archivo main.py tendrá el siguiente aspecto:


# main.py
from typing import List
from uuid import uuid4
from fastapi import FastAPI
from models import Gender, Role, User
app = FastAPI()
db: List[User] = [
 User(
 id=uuid4(),
 first_name="John",
 last_name="Doe",
 gender=Gender.male,
 roles=[Role.user],
 ),
 User(
 id=uuid4(),
 first_name="Jane",
 last_name="Doe",
 gender=Gender.female,
 roles=[Role.user],
 ),
 User(
 id=uuid4(),
 first_name="James",
 last_name="Gabriel",
 gender=Gender.male,
 roles=[Role.user],
 ),
 User(
 id=uuid4(),
 first_name="Eunit",
 last_name="Eunit",
 gender=Gender.male,
 roles=[Role.admin, Role.user],
 ),
]
@app.get("/")
async def root():
 return {"Hello": "World",}
@app.get("/api/v1/users")
async def get_users():
 return db

Crear Registros de la Base de Datos

El siguiente paso es crear un endpoint para crear un nuevo usuario en tu base de datos. Pega el siguiente fragmento en tu archivo main.py:


# main.py
@app.post("/api/v1/users")
async def create_user(user: User):
 db.append(user)
 return {"id": user.id}

En este fragmento, has definido el endpoint para enviar un nuevo usuario y has utilizado el decorador @app.post para crear un método POST.

También has creado la función create_user, que acepta user del modelo User, y has anexado (añadido) el recién creado user a la base de datos, db. Finalmente, el endpoint devuelve un objeto JSON del usuario recién creado id.

Tendrás que utilizar la documentación automática de la API proporcionada por FastAPI para probar tu punto final, como se ha visto anteriormente. Esto se debe a que no puedes hacer una solicitud de post con el navegador web. Navega a http://localhost:8000/docs para probar utilizando la documentación proporcionada por SwaggerUI.

Parámetros para una petición POST de FastAPI.
Parámetros para una petición POST de FastAPI.

Eliminar Registros de la Base de Datos

Como estás construyendo una aplicación CRUD, tu aplicación necesitará tener la capacidad de eliminar un recurso específico. Para este tutorial, crearás un endpoint para eliminar un usuario.

Pega el siguiente código en tu archivo main.py:


# main.py
from uuid import UUID
from fastapi HTTPException
@app.delete("/api/v1/users/{id}")
async def delete_user(id: UUID):
for user in db:
 if user.id == id:
 db.remove(user)
 return
raise HTTPException(
 status_code=404, detail=f"Delete user failed, id {id} not found."
 )

Aquí tienes un desglose línea por línea de cómo funciona ese código:

  • @app.delete("/api/v1/users/{id}"): Has creado el endpoint de eliminación utilizando el decorador @app.delete(). La ruta sigue siendo /api/v1/users/{id}, pero entonces recupera la id, que es una variable de ruta correspondiente al id del usuario.
  • async def delete_user(id: UUID):: Crea la función delete_user, que recupera el id de la URL.
  • for user in db:: Esto le dice a la aplicación que haga un bucle a través de los usuarios de la base de datos, y compruebe si el id pasado coincide con un usuario de la base de datos.
  • db.remove(user): Si el id coincide con un usuario, éste será eliminado; en caso contrario, se lanzará un HTTPException con un código de estado 404.
Parámetros para una petición DELETE de FastAPI.
Parámetros para una petición DELETE de FastAPI.

Actualizar Registros de la Base de Datos

Vas a crear un endpoint para actualizar los detalles de un usuario. Los detalles que se pueden actualizar incluyen los siguientes parámetros: first_name, last_name, y roles.

En tu archivo models.py, pega el siguiente código bajo tu modelo User, es decir, después de la clase User(BaseModel)::

 # models.py
 class UpdateUser(BaseModel):
 first_name: Optional[str]
 last_name: Optional[str]
 roles: Optional[List[Role]]

En este fragmento, la clase UpdateUser extiende BaseModel. A continuación, establece que los parámetros de usuario actualizables, como first_name, last_name, y roles, sean opcionales.

Ahora crearás un endpoint para actualizar los datos de un usuario concreto. En tu archivo main.py, pega el siguiente código después del decorador @app.delete:

# main.py
@app.put("/api/v1/users/{id}")
async def update_user(user_update: UpdateUser, id: UUID):
 for user in db:
 if user.id == id:
 if user_update.first_name is not None:
 user.first_name = user_update.first_name
 if user_update.last_name is not None:
 user.last_name = user_update.last_name
 if user_update.roles is not None:
 user.roles = user_update.roles
 return user.id
 raise HTTPException(status_code=404, detail=f"Could not find user with id: {id}")

En el código anterior, has hecho lo siguiente

  • Creado @app.put("/api/v1/users/{id}"), el punto final de actualización. Tiene un parámetro variable id que corresponde al id del usuario.
  • Creó un método llamado update_user, que toma la clase UpdateUser y id.
  • Utiliza un bucle for para comprobar si el usuario asociado al id pasado está en la base de datos.
  • Comprueba si alguno de los parámetros del usuario es is not None (no nulo). Si algún parámetro, como first_name, last_name, o roles, no es nulo, se actualiza.
  • Si la operación tiene éxito, se devuelve el identificador del usuario.
  • Si no se localiza al usuario, se lanza una excepción HTTPException con un código de estado 404 y un mensaje Could not find user with id: {id}.

Para probar este endpoint, asegúrate de que tu servidor Uvicorn se está ejecutando. Si no se está ejecutando, introduce este comando:

uvicorn main:app --reload

A continuación se muestra una captura de pantalla de la prueba.

Parámetros de una solicitud FastAPI UPDATE.
Parámetros de una solicitud FastAPI UPDATE.

Resumen

En este tutorial, has conocido el framework FastAPI para Python y has comprobado por ti mismo lo rápido que puedes poner en marcha una aplicación potenciada por FastAPI. Has aprendido a construir endpoints de la API CRUD utilizando el framework: crear, leer, actualizar y eliminar registros de la base de datos.

Ahora, si quieres llevar el desarrollo de tu aplicación web a un nivel superior, asegúrate de consultar la plataforma de Kinsta para el alojamiento de aplicaciones y bases de datos. Al igual que FastAPI, es potentemente sencilla.

Emmanuel Uchenna

Emmanuel es un desarrollador de software y redactor técnico experimentado, apasionado y entusiasta, con años de experiencia profesional demostrada. Se centra en el desarrollo web full-stack. Domina ReactJS, JavaScript, VueJS y NodeJS y está familiarizado con tecnologías estándar del sector como Git, GitHub y TDD. Ayuda a particulares, empresas y marcas a crear sitios web responsivos, accesibles, bonitos e intuitivos para mejorar su presencia en Internet. También es redactor técnico para varios sitios web y sus propios proyectos.