my_api_fastapi / app.py
dinho1597's picture
Rename main.py to app.py
4ffb2b7 verified
# main.py
from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel
from typing import Optional, List
# --- Modelos de Datos con Pydantic ---
# Pydantic se encarga de la validación y serialización de datos
class Item(BaseModel):
"""Modelo base para un ítem. Todos los campos son requeridos."""
id: int
name: str
description: Optional[str] = None
price: float
class UpdateItem(BaseModel):
"""Modelo para actualizar un ítem. Todos los campos son opcionales."""
name: Optional[str] = None
description: Optional[str] = None
price: Optional[float] = None
# --- Instancia de la Aplicación FastAPI ---
app = FastAPI(
title="API de Ejemplo Completa",
description="Una API de ejemplo con todos los métodos HTTP para demostrar FastAPI, Docker y Hugging Face Spaces.",
version="1.0.0",
)
# --- "Base de Datos" en Memoria ---
# Un diccionario simple para simular una base de datos.
db = {
1: Item(id=1, name="Laptop", description="Un potente portátil para desarrollo", price=1200.50),
2: Item(id=2, name="Teclado Mecánico", description="Un teclado con switches Cherry MX Blue", price=150.75),
}
# --- Endpoints de la API ---
@app.get("/", tags=["Root"])
def read_root():
"""Endpoint principal de bienvenida."""
return {"message": "¡Bienvenido a la API de ejemplo con FastAPI!"}
# --- Métodos para la colección de ítems ---
@app.get("/items", response_model=List[Item], tags=["Items"])
def get_all_items():
"""
GET: Obtiene una lista de todos los ítems en la base de datos.
"""
return list(db.values())
@app.post("/items", response_model=Item, status_code=status.HTTP_201_CREATED, tags=["Items"])
def create_item(item: Item):
"""
POST: Crea un nuevo ítem.
El ID del ítem en el cuerpo de la petición debe ser único.
"""
if item.id in db:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"El ítem con ID {item.id} ya existe."
)
db[item.id] = item
return item
# --- Métodos para un ítem específico ---
@app.get("/items/{item_id}", response_model=Item, tags=["Items"])
def get_item_by_id(item_id: int):
"""
GET: Obtiene un ítem específico por su ID.
"""
if item_id not in db:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"El ítem con ID {item_id} no fue encontrado."
)
return db[item_id]
@app.put("/items/{item_id}", response_model=Item, tags=["Items"])
def update_item_completely(item_id: int, item: Item):
"""
PUT: Actualiza un ítem completamente.
Reemplaza toda la información del ítem existente con la nueva.
"""
if item_id not in db:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"El ítem con ID {item_id} no fue encontrado."
)
# El ID no debe cambiar en una operación PUT
if item_id != item.id:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="El ID del ítem en la URL no coincide con el ID en el cuerpo de la petición."
)
db[item_id] = item
return db[item_id]
@app.patch("/items/{item_id}", response_model=Item, tags=["Items"])
def update_item_partially(item_id: int, item_update: UpdateItem):
"""
PATCH: Actualiza un ítem parcialmente.
Solo actualiza los campos proporcionados en el cuerpo de la petición.
"""
if item_id not in db:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"El ítem con ID {item_id} no fue encontrado."
)
stored_item_data = db[item_id].dict()
update_data = item_update.dict(exclude_unset=True) # Obtiene solo los campos que se enviaron
updated_item_data = stored_item_data.copy()
updated_item_data.update(update_data)
db[item_id] = Item(**updated_item_data)
return db[item_id]
@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT, tags=["Items"])
def delete_item(item_id: int):
"""
DELETE: Elimina un ítem por su ID.
Devuelve un código 204 sin contenido si tiene éxito.
"""
if item_id not in db:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"El ítem con ID {item_id} no fue encontrado."
)
del db[item_id]
# No se devuelve contenido, solo el código de estado 204
return