Tutorial FastAPI Python: Cómo Crear una API RESTful Paso a Paso
FastAPI es uno de los frameworks más populares para construir APIs RESTful con Python, gracias a su sencillez, rapidez y soporte para validación de datos mediante Pydantic. En este tutorial detallado, aprenderás desde la instalación hasta cómo crear rutas CRUD, manejar errores, integrar una base de datos SQLite con SQLAlchemy y probar tu API. Es ideal para desarrolladores principiantes e intermedios que quieran iniciarse en el desarrollo backend moderno con Python.
Índice
- 1. Instalación y Configuración del Entorno
- 2. Creación de la API Básica con Rutas CRUD
- 3. Validación de Datos con Pydantic
- 4. Manejo de Respuestas y Errores
- 5. Integración con SQLite y SQLAlchemy
- 6. Pruebas Básicas con Postman y curl
- Conclusión y Buenas Prácticas
1. Instalación y Configuración del Entorno
Paso 1: Crear y activar un entorno virtual
Para aislar tus dependencias, es recomendable usar un entorno virtual.
1 2 3 4 5 6 7 8 9 |
# Crear el entorno virtual python3 -m venv fastapi-env # Activar el entorno virtual (Linux/macOS) source fastapi-env/bin/activate # Activar el entorno virtual (Windows) fastapi-env\Scripts\activate |
Paso 2: Instalar FastAPI y Uvicorn
FastAPI es el framework y Uvicorn es un servidor ASGI ligero para correr la aplicación.
1 2 |
pip install fastapi uvicorn |
Paso 3: Crear la estructura inicial
Crea un archivo llamado main.py
donde estará nuestra API.
2. Creación de la API Básica con Rutas CRUD
Vamos a construir una API básica para gestionar “items” (elementos) con operaciones CRUD: Crear, Leer, Actualizar y Eliminar.
Paso 1: Estructura básica con FastAPI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from fastapi import FastAPI app = FastAPI() # Datos en memoria (lista) para ejemplo simple items = [] @app.get("/items/") def read_items(): return items @app.post("/items/") def create_item(item: dict): items.append(item) return item |
Este código crea dos rutas:
- GET para listar items
- POST para añadir un item
Paso 2: Añadir rutas para Leer, Actualizar y Eliminar por ID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from fastapi import HTTPException @app.get("/items/{item_id}") def read_item(item_id: int): if item_id >= len(items) or item_id < 0: raise HTTPException(status_code=404, detail="Item no encontrado") return items[item_id] @app.put("/items/{item_id}") def update_item(item_id: int, item: dict): if item_id >= len(items) or item_id < 0: raise HTTPException(status_code=404, detail="Item no encontrado") items[item_id] = item return item @app.delete("/items/{item_id}") def delete_item(item_id: int): if item_id >= len(items) or item_id < 0: raise HTTPException(status_code=404, detail="Item no encontrado") return items.pop(item_id) |
3. Validación de Datos con Pydantic
FastAPI utiliza Pydantic para definir modelos y validar automáticamente los datos recibidos.
Paso 1: Definir el modelo Item con Pydantic
1 2 3 4 5 6 7 8 |
from pydantic import BaseModel class Item(BaseModel): name: str description: str = None price: float tax: float = None |
Paso 2: Usar el modelo para validar las rutas POST y PUT
1 2 3 4 5 6 7 8 9 10 11 12 |
@app.post("/items/", response_model=Item) def create_item(item: Item): items.append(item) return item @app.put("/items/{item_id}", response_model=Item) def update_item(item_id: int, item: Item): if item_id >= len(items) or item_id < 0: raise HTTPException(status_code=404, detail="Item no encontrado") items[item_id] = item return item |
Ahora FastAPI valida automáticamente que los datos enviados coincidan con el esquema Item
. Esto previene errores y mejora la robustez.
4. Manejo de Respuestas y Errores
Para una API profesional, debes manejar adecuadamente respuestas y errores.
Usar códigos HTTP adecuados
1 2 3 4 5 6 7 |
from fastapi import status @app.post("/items/", status_code=status.HTTP_201_CREATED, response_model=Item) def create_item(item: Item): items.append(item) return item |
Manejo personalizado de errores
1 2 3 4 5 6 7 |
@app.get("/items/{item_id}") def read_item(item_id: int): try: return items[item_id] except IndexError: raise HTTPException(status_code=404, detail="Item no encontrado") |
FastAPI provee clases para lanzar excepciones HTTP que se traducen correctamente en las respuestas de la API.
5. Integración con SQLite y SQLAlchemy
Guardar datos en memoria no es viable para producción. Veamos cómo integrar FastAPI con SQLite usando SQLAlchemy.
Paso 1: Instalar dependencias necesarias
1 2 |
pip install sqlalchemy databases[sqlite] asyncpg alembic |
Para este ejemplo usaremos SQLAlchemy 1.4 o superior con soporte asíncrono.
Paso 2: Configurar la base de datos y modelos
Crea un archivo database.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, Float from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db" engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() class ItemDB(Base): __tablename__ = "items" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True) description = Column(String, nullable=True) price = Column(Float) tax = Column(Float, nullable=True) |
Paso 3: Crear la base de datos
1 2 |
Base.metadata.create_all(bind=engine) |
Puedes ejecutarlo en un script aparte o dentro de main.py
si es apropiado.
Paso 4: Añadir dependencia para obtener sesión de DB
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from fastapi import Depends from sqlalchemy.orm import Session from database import SessionLocal # Dependencia para obtener sesión def get_db(): db = SessionLocal() try: yield db finally: db.close() |
Paso 5: Actualizar rutas para usar base de datos
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
from sqlalchemy.orm import Session from fastapi import Depends from database import ItemDB, get_db @app.post("/items/", response_model=Item) def create_item(item: Item, db: Session = Depends(get_db)): db_item = ItemDB(**item.dict()) db.add(db_item) db.commit() db.refresh(db_item) return db_item @app.get("/items/{item_id}", response_model=Item) def read_item(item_id: int, db: Session = Depends(get_db)): db_item = db.query(ItemDB).filter(ItemDB.id == item_id).first() if db_item is None: raise HTTPException(status_code=404, detail="Item no encontrado") return db_item @app.delete("/items/{item_id}") def delete_item(item_id: int, db: Session = Depends(get_db)): db_item = db.query(ItemDB).filter(ItemDB.id == item_id).first() if db_item is None: raise HTTPException(status_code=404, detail="Item no encontrado") db.delete(db_item) db.commit() return {"detail": "Item eliminado"} @app.put("/items/{item_id}", response_model=Item) def update_item(item_id: int, item: Item, db: Session = Depends(get_db)): db_item = db.query(ItemDB).filter(ItemDB.id == item_id).first() if db_item is None: raise HTTPException(status_code=404, detail="Item no encontrado") for key, value in item.dict().items(): setattr(db_item, key, value) db.commit() db.refresh(db_item) return db_item |
6. Pruebas Básicas con Postman y curl
Para probar la API, usaremos herramientas comunes.
Probar con curl
- Crear un item
1 2 |
curl -X POST "http://127.0.0.1:8000/items/" -H "Content-Type: application/json" -d '{"name":"Producto1", "description":"Descripción", "price":10.5, "tax":1.5}' |
- Obtener un item
1 2 |
curl http://127.0.0.1:8000/items/1 |
- Actualizar un item
1 2 |
curl -X PUT "http://127.0.0.1:8000/items/1" -H "Content-Type: application/json" -d '{"name":"Producto1 mod", "description":"Nueva descripción", "price":12, "tax":2}' |
- Eliminar un item
1 2 |
curl -X DELETE http://127.0.0.1:8000/items/1 |
Probar con Postman
- Abre Postman.
- Crea una nueva petición.
- Selecciona el método HTTP (GET, POST, PUT, DELETE).
- Pon la URL (p.ej. http://127.0.0.1:8000/items/).
- Si haces POST o PUT, en la pestaña “Body”, selecciona “raw” y “JSON”. Pega el JSON con los datos.
- Envía la petición y revisa la respuesta.
Conclusión y Buenas Prácticas
En este tutorial FastAPI Python has aprendido:
- Cómo instalar y configurar un entorno para FastAPI.
- Crear rutas básicas CRUD para una API RESTful.
- Validar y serializar datos con Pydantic.
- Manejar respuestas y errores adecuadamente.
- Integrar la API con una base de datos SQLite usando SQLAlchemy.
- Probar tu API con herramientas como Postman y curl.
Buenas prácticas recomendadas:
- Define modelos claros con Pydantic para validar datos.
- Maneja excepciones y devuelve mensajes claros para el cliente.
- Utiliza dependencias para manejar conexiones a la base de datos.
- Mantén tu código modular y bien documentado.
- Escribe tests automatizados para asegurar la calidad.
- Usa migraciones (ej. Alembic) cuando trabajes con modelos y base de datos.
Ahora estás listo para expandir esta API, agregar autenticación, pagination, documentación automática y mucho más.
¡Empieza a crear APIs REST con FastAPI para principiantes y avanza en el desarrollo backend Python moderno!
Ejecutar servidor
Para iniciar la API, usa:
1 2 |
uvicorn main:app --reload |
El flag --reload
recarga el servidor automáticamente al cambiar código.
¡Gracias por leer este tutorial FastAPI Python!