Tutorial: Integrar OpenAI API en Python paso a paso
Desde tu primera llamada a GPT hasta un sistema completo con streaming, function calling y manejo de errores. Código production-ready.
Configuración paso a paso de un proyecto FastAPI con SQLAlchemy 2.0 (async), Alembic para migraciones y Pydantic v2 para schemas.
Cómo configurar un proyecto FastAPI con SQLAlchemy async, Alembic para migraciones, y Pydantic v2 para schemas. Desde cero hasta tener un CRUD funcionando.
pip install fastapi uvicorn sqlalchemy[asyncio] asyncpg alembic pydantic-settings
project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── config.py
│ ├── database.py
│ ├── models.py
│ └── schemas.py
├── alembic/
│ ├── versions/
│ └── env.py
├── alembic.ini
└── requirements.txt
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from sqlalchemy.orm import DeclarativeBase
from app.config import get_settings
engine = create_async_engine(
get_settings().database_url,
echo=get_settings().debug,
pool_size=20,
max_overflow=10,
)
async_session = async_sessionmaker(engine, expire_on_commit=False)
class Base(DeclarativeBase):
pass
async def get_db() -> AsyncSession:
async with async_session() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
from datetime import datetime
from sqlalchemy import String, Text, DateTime, func
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class Item(Base):
__tablename__ = "items"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100), index=True)
description: Mapped[str | None] = mapped_column(Text, default=None)
price: Mapped[float]
is_active: Mapped[bool] = mapped_column(default=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
)
from pydantic import BaseModel, Field
from datetime import datetime
class ItemCreate(BaseModel):
name: str = Field(min_length=1, max_length=100)
description: str | None = None
price: float = Field(gt=0)
class ItemUpdate(BaseModel):
name: str | None = Field(None, min_length=1, max_length=100)
description: str | None = None
price: float | None = Field(None, gt=0)
is_active: bool | None = None
class ItemResponse(BaseModel):
id: int
name: str
description: str | None
price: float
is_active: bool
created_at: datetime
model_config = {"from_attributes": True}
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from app.models import Item
from app.schemas import ItemCreate, ItemUpdate, ItemResponse
app = FastAPI()
@app.post("/items", response_model=ItemResponse, status_code=201)
async def create_item(data: ItemCreate, db: AsyncSession = Depends(get_db)):
item = Item(**data.model_dump())
db.add(item)
await db.flush()
await db.refresh(item)
return item
@app.get("/items", response_model=list[ItemResponse])
async def list_items(
skip: int = 0, limit: int = 20,
db: AsyncSession = Depends(get_db),
):
result = await db.execute(
select(Item).where(Item.is_active).offset(skip).limit(limit)
)
return result.scalars().all()
@app.patch("/items/{item_id}", response_model=ItemResponse)
async def update_item(
item_id: int, data: ItemUpdate,
db: AsyncSession = Depends(get_db),
):
result = await db.execute(select(Item).where(Item.id == item_id))
item = result.scalar_one_or_none()
if not item:
raise HTTPException(404, "Item no encontrado")
for key, value in data.model_dump(exclude_unset=True).items():
setattr(item, key, value)
await db.flush()
await db.refresh(item)
return item
# Inicializar Alembic (solo una vez)
alembic init alembic
# Editar alembic/env.py: importar Base.metadata
# Editar alembic.ini: sqlalchemy.url = postgresql://...
# Crear migración
alembic revision --autogenerate -m "create items table"
# Aplicar migraciones
alembic upgrade head
# Ver historial
alembic history
# Agregar al inicio de env.py:
from app.database import Base
from app.models import Item # Importar todos los modelos
target_metadata = Base.metadata
Este recurso incluye un enlace externo. Regístrate para acceder.
Regístrate gratis para descargar archivos, guardar recursos en favoritos, ganar XP y acceder a cursos y el foro de la comunidad.
¿Ya tienes cuenta? Inicia sesión
Autor
Erik Taveras
Creado por
Erik Taveras
Desde tu primera llamada a GPT hasta un sistema completo con streaming, function calling y manejo de errores. Código production-ready.
Implementación paso a paso de Stripe Checkout para cobros únicos y suscripciones en Django. Incluye webhooks, portal del cliente y manejo de estados.
Comparativa práctica entre REST y GraphQL con ejemplos en Python. Ventajas, desventajas y criterios de decisión para tu próximo proyecto.