En los últimos años, se ha producido una verdadera revolución en el mundo del desarrollo de Python. Cada vez más equipos están eligiendo FastAPI para nuevos proyectos, desplazando gradualmente a Django, un marco que ha sido el estándar de la industria durante muchos años. Veamos qué está pasando y por qué los desarrolladores principiantes deberían prestar atención a FastAPI.
¿Qué es FastAPI y Django?
Django es un marco web con todas las funciones que existe desde 2005. Fue creado para desarrollar aplicaciones web completas con un panel de administración incorporado, ORM, un sistema de plantillas y muchas otras características «listas para usar».
FastAPI es un marco moderno que apareció en 2018, creado específicamente para el desarrollo de API. Se basa en las capacidades modernas de Python 3.7+ y la programación asíncrona.
¿Por qué FastAPI está ganando popularidad?
1. Rendimiento como Go y Node.js
FastAPI es uno de los frameworks de Python más rápidos gracias a su asincronicidad. Aquí hay una comparación simple:
# Django (enfoque síncrono)
from django.http import JsonResponse
def get_users(request):
users = User.objects.all() # Solicitud de bloqueo
return JsonResponse({'users': list(users.values())})# FastAPI (enfoque asíncrono)
from fastapi import FastAPI
from typing import List
app = FastAPI()
@app.get("/users")
async def get_users() -> List[dict]:
users = await database.fetch_all("SELECT * FROM users")
return users💡 Importante: En FastAPI, las consultas se procesan de forma asíncrona, lo que permite al servidor atender miles de conexiones al mismo tiempo sin bloqueos. Django también admite la asincronía desde la versión 3.1, pero el ecosistema aún no está completamente adaptado.
2. Un comienzo increíblemente fácil
Puedes crear la primera API en FastAPI en solo 5 minutos:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello, world!"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}Ejecutamos con el comando:
uvicorn main:app --reload✅ ¡Y ya está! Ya tienes una API en funcionamiento. Sin ajustes, archivos de configuración o estructuras de proyecto complejas.
3. La documentación automática es magia
Una de las características más interesantes de FastAPI es la documentación interactiva automática. Simplemente abre http://localhost:8000/docs y verás la documentación completa de la interfaz de usuario de Swagger, donde puedes probar cada punto final directamente en el navegador.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(
title="My project's API",
description="Description of all endpoints",
version="1.0.0"
)
class Item(BaseModel):
name: str
description: str = None
price: float
@app.post("/items/")
async def create_item(item: Item):
"""
Creating a new product:
- **name**: product name
- **description**: description (optional)
- **price**: product price
"""
return {"item": item}La documentación se genera automáticamente a partir de tipos de datos y cadenas de documentación. En Django, para ello se deben utilizar bibliotecas adicionales como drf-spectacular.
4. Tipificación y validación desde la caja
FastAPI utiliza Pydantic para la validación automática de datos:
from pydantic import BaseModel, EmailStr, validator
from typing import Optional
class User(BaseModel):
username: str
email: EmailStr
age: Optional[int] = None
@validator('age')
def age_must_be_positive(cls, v):
if v is not None and v < 0:
raise ValueError('Age cannot be negative')
return v
@app.post("/users/")
async def create_user(user: User):
# Si los datos no son válidos, FastAPI devolverá automáticamente un error 422
# con una descripción detallada del problema
return {"user": user}Si envías datos no válidos, recibirás un error comprensible que indica todos los problemas.
5. Trabajo moderno con adicciones
Dependency Injection en FastAPI hace que el código sea limpio y comprobable:
from fastapi import Depends, HTTPException
from sqlalchemy.orm import Session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
def get_current_user(token: str = Header(...)):
user = verify_token(token)
if not user:
raise HTTPException(status_code=401, detail="Unauthorized")
return user
@app.get("/users/me")
async def read_current_user(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
return current_userLas dependencias se resuelven e implementan automáticamente. Esto hace que las pruebas sean increíblemente fáciles.
6. WebSocket y tareas en segundo plano
from fastapi import WebSocket, BackgroundTasks
import time
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Received: {data}")
def write_log(message: str):
time.sleep(5) # Operación larga
with open("log.txt", "a") as f:
f.write(message)
@app.post("/send-notification/")
async def send_notification(
email: str,
background_tasks: BackgroundTasks
):
background_tasks.add_task(write_log, f"Sent to {email}")
return {"message": "Notification will be sent"}
¿Cuándo elegir Django?
FastAPI no siempre es la mejor opción. Django es preferible si necesitas:
Aplicación web completa con panel de administración — Django Admin listo para usar
Sistema de autenticación y permisos — lista y probada en el tiempo
ORM con migraciones — Django ORM es más fácil para los principiantes
Sistema de plantillas integrado — si necesitas renderización del lado del servidor
Un enorme ecosistema de paquetes — Django existe desde hace 19 años
Ejemplo práctico: API CRUD
Vamos a crear una API CRUD sencilla para gestionar tareas:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
from datetime import datetime
app = FastAPI()
class Task(BaseModel):
id: Optional[int] = None
title: str
description: Optional[str] = None
completed: bool = False
created_at: Optional[datetime] = None
# Almacenamiento temporal (en realidad, usa la base de datos)
tasks_db = []
task_id_counter = 1
@app.post("/tasks/", response_model=Task)
async def create_task(task: Task):
global task_id_counter
task.id = task_id_counter
task.created_at = datetime.now()
task_id_counter += 1
tasks_db.append(task)
return task
@app.get("/tasks/", response_model=List[Task])
async def get_tasks(completed: Optional[bool] = None):
if completed is None:
return tasks_db
return [t for t in tasks_db if t.completed == completed]
@app.get("/tasks/{task_id}", response_model=Task)
async def get_task(task_id: int):
task = next((t for t in tasks_db if t.id == task_id), None)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
return task
@app.put("/tasks/{task_id}", response_model=Task)
async def update_task(task_id: int, task_update: Task):
task = next((t for t in tasks_db if t.id == task_id), None)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
task.title = task_update.title
task.description = task_update.description
task.completed = task_update.completed
return task
@app.delete("/tasks/{task_id}")
async def delete_task(task_id: int):
global tasks_db
tasks_db = [t for t in tasks_db if t.id != task_id]
return {"message": "Task deleted"}Integración con la base de datos
FastAPI funciona muy bien con SQLAlchemy:
from sqlalchemy import create_engine, Column, Integer, String, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./tasks.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class TaskModel(Base):
__tablename__ = "tasks"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
description = Column(String)
completed = Column(Boolean, default=False)
Base.metadata.create_all(bind=engine)
@app.post("/tasks/", response_model=Task)
async def create_task(task: Task, db: Session = Depends(get_db)):
db_task = TaskModel(**task.dict(exclude={'id'}))
db.add(db_task)
db.commit()
db.refresh(db_task)
return db_taskAutenticación y seguridad
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from passlib.context import CryptContext
from jose import JWTError, jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=30)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials"
)
access_token = create_access_token(data={"sub": user.username})
return {"access_token": access_token, "token_type": "bearer"}
async def get_current_user(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(status_code=401)
return username
except JWTError:
raise HTTPException(status_code=401)
@app.get("/users/me")
async def read_users_me(current_user: str = Depends(get_current_user)):
return {"username": current_user}Pruebas
FastAPI hace que las pruebas sean fáciles:
from fastapi.testclient import TestClient
client = TestClient(app)
def test_create_task():
response = client.post(
"/tasks/",
json={"title": "Test task", "description": "Description"}
)
assert response.status_code == 200
assert response.json()["title"] == "Test task"
def test_get_tasks():
response = client.get("/tasks/")
assert response.status_code == 200
assert isinstance(response.json(), list)Rendimiento: hechos y cifras
Según TechEmpower Benchmarks (2026):
Marco | Consultas por segundo | Productividad |
|---|---|---|
FastAPI | ~60,000 | ⭐⭐⭐⭐⭐ |
Django Ninja | ~40,000 | ⭐⭐⭐⭐ |
Django + gunicorn | ~10,000 | ⭐⭐⭐ |
🚀 Conclusión: ¡FastAPI puede procesar 6 veces más solicitudes con la misma carga!
En Codice encontrarás cursos detallados sobre Python, FastAPI, Django y otras tecnologías modernas. Enseñamos programación en la práctica, con proyectos reales y explicaciones claras.
🚀 Únete a nuestro canal de Telegram — aquí encontrarás una comunidad de desarrolladores amigable, materiales útiles, análisis de código y respuestas a tus preguntas. ¡Te ayudaremos a convertirte en un especialista muy solicitado!
Comienza tu viaje de programación con Kodik: ¡aprende de forma cómoda, rápida y eficaz!
