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.
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étodoGET
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.
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.
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.
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.
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 usuariolast_name
: El apellido del usuariogender
: El género del usuarioroles
que es una lista que contiene los rolesadmin
yuser
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
extiendeBaseModel
, que a su vez se importa depydantic
. - 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 tipoList
, y has pasado el modeloUser
- Creaste una base de datos en memoria con cuatro usuarios, cada uno con los atributos necesarios como
first_name
,last_name
,gender
, yroles
. Al usuarioEunit
se le asignan los roles deadmin
yuser
, mientras que a los otros tres usuarios sólo se les asigna el rol deuser
.
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:
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.
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 laid
, que es una variable de ruta correspondiente al id del usuario.async def delete_user(id: UUID):
: Crea la funcióndelete_user
, que recupera elid
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 elid
pasado coincide con un usuario de la base de datos.db.remove(user)
: Si elid
coincide con un usuario, éste será eliminado; en caso contrario, se lanzará unHTTPException
con un código de estado 404.
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 variableid
que corresponde al id del usuario. - Creó un método llamado
update_user
, que toma la claseUpdateUser
yid
. - Utiliza un bucle
for
para comprobar si el usuario asociado alid
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, comofirst_name
,last_name
, oroles
, 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 mensajeCould 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.
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.
Deja una respuesta