Configuración de Flask con MongoDB de forma segura
La primera vez que alguien conecta Flask con MongoDB suele hacerlo en menos de diez minutos. Instalas dos librerías, copias una cadena de conexión y listo: ya puedes guardar documentos.
El problema es que esa rapidez viene con una trampa silenciosa. Muchos ejemplos que circulan por internet funcionan para una demo, pero dejan varias puertas abiertas: credenciales en el código, conexiones mal manejadas, validaciones inexistentes y una base de datos que podría terminar expuesta si el proyecto llega a producción.
La idea de este post no es hacer algo complicado. Al contrario: construir una base simple, ordenada y razonablemente segura para empezar un backend con Flask y MongoDB sin arrastrar malas prácticas desde el inicio.
1. Preparar el entorno de trabajo
Antes de escribir código conviene aislar el proyecto. Python tiene una herramienta simple para eso: los entornos virtuales.
Crear uno evita conflictos entre dependencias de distintos proyectos.
1
python -m venv venv
Activarlo en Linux o macOS:
1
source venv/bin/activate
Una vez activo, instalamos las librerías necesarias.
1
pip install flask pymongo python-dotenv
Guardar las dependencias es una buena costumbre desde el primer momento.
1
pip freeze > requirements.txt
Esto permite reconstruir el entorno completo en otro equipo o servidor.
Si quieres saber más sobre entornos virtuales, revisa Entornos virtuales en Python.
2. Pensar la estructura antes de codificar
Muchos tutoriales empiezan directamente con un archivo app.py. Funciona, pero a medida que el proyecto crece ese archivo termina acumulando rutas, lógica de base de datos y configuración.
Una estructura pequeña pero organizada podría verse así:
1
2
3
4
5
6
7
8
9
10
11
project/
│
├─ app/
│ ├─ __init__.py
│ ├─ config.py
│ ├─ db.py
│ └─ routes.py
│
├─ .env
├─ requirements.txt
└─ run.py
La idea es separar responsabilidades:
- configuración
- conexión a base de datos
- rutas de la API
- punto de arranque
Esto mantiene el proyecto legible incluso cuando empieza a crecer.
3. Evitar credenciales en el código
Un error extremadamente común en desarrollo es escribir directamente la cadena de conexión en el código fuente.
Algo así:
1
client = MongoClient("mongodb://localhost:27017/mydatabase")
Funciona, pero es mala práctica. Las credenciales deberían vivir en variables de entorno.
Creamos un archivo .env.
1
2
3
4
FLASK_ENV=development
SECRET_KEY=change-this-secret
MONGO_URI=mongodb://localhost:27017/mydatabase
Luego creamos config.py para leer estas variables.
1
2
3
4
5
6
7
8
import os
from dotenv import load_dotenv
load_dotenv()
class Config:
SECRET_KEY = os.getenv("SECRET_KEY")
MONGO_URI = os.getenv("MONGO_URI")
Esto permite cambiar configuraciones sin modificar el código.
4. Crear una conexión centralizada a MongoDB
Abrir conexiones nuevas constantemente puede afectar el rendimiento. Lo más limpio es inicializar un cliente una vez y reutilizarlo.
Archivo db.py.
1
2
3
4
5
6
7
8
9
10
from pymongo import MongoClient
client = None
db = None
def init_db(app):
global client, db
client = MongoClient(app.config["MONGO_URI"])
db = client.get_default_database()
La aplicación usará siempre esa misma conexión.
5. Inicializar Flask usando el patrón Application Factory
Flask permite crear aplicaciones de forma flexible. Un patrón muy usado es Application Factory, que crea la app mediante una función.
Archivo app/__init__.py.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from flask import Flask
from .config import Config
from .db import init_db
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
init_db(app)
from .routes import main
app.register_blueprint(main)
return app
Este enfoque evita dependencias circulares y facilita pruebas o configuraciones diferentes.
6. Crear una ruta simple para comprobar la conexión
Antes de construir endpoints complejos conviene verificar que todo funciona.
Archivo routes.py.
1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Blueprint, jsonify
from .db import db
main = Blueprint("main", __name__)
@main.route("/health")
def health():
collections = db.list_collection_names()
return jsonify({
"status": "ok",
"collections": collections
})
Este endpoint sirve como comprobación rápida de que la aplicación puede comunicarse con la base de datos.
7. Ejecutar la aplicación
Archivo run.py.
1
2
3
4
5
6
from app import create_app
app = create_app()
if __name__ == "__main__":
app.run(debug=True)
Luego ejecutas:
1
python run.py
Si todo está correcto, la API estará disponible en http://localhost:5000.
8. Crear usuarios en MongoDB
Aunque MongoDB esté instalado localmente, es recomendable habilitar autenticación.
En la consola de MongoDB:
1
2
3
4
5
6
7
use admin
db.createUser({
user: "api_user",
pwd: "strong_password",
roles: [{ role: "readWrite", db: "mydatabase" }]
})
Al ejecutar
db.createUser()en MongoDB, el servidor responde con un documento JSON indicando el éxito({ "ok": 1 })o un mensaje de error si el usuario ya existe o falta información.
Luego la URI de conexión se vería así:
1
mongodb://api_user:password@localhost:27017/mydatabase
Esto evita que cualquier proceso local pueda manipular la base de datos.
9. Validar los datos antes de guardarlos
MongoDB permite guardar prácticamente cualquier estructura. Eso es flexible, pero también peligroso.
Evita insertar directamente lo que llega en una request.
Mala práctica:
1
db.users.insert_one(request.json)
Mejor controlar los campos.
1
2
3
4
5
6
7
8
data = request.json
user = {
"username": data.get("username"),
"email": data.get("email")
}
db.users.insert_one(user)
Esto reduce errores y previene datos inconsistentes.
10. Crear índices temprano
Los índices mejoran el rendimiento y pueden imponer reglas de unicidad.
Por ejemplo, para evitar correos duplicados:
1
db.users.create_index("email", unique=True)
Si intentas insertar dos documentos con el mismo email, MongoDB lanzará un error.
11. Manejar correctamente los ObjectId
MongoDB utiliza ObjectId como identificador interno. Ese tipo no es serializable directamente a JSON.
Una solución simple es convertirlo a string.
1
2
3
def serialize(doc):
doc["_id"] = str(doc["_id"])
return doc
Esto permite devolver documentos en respuestas de la API sin errores.
12. Mantener MongoDB fuera de internet
Una arquitectura básica segura se ve así:
1
Cliente → API Flask → MongoDB
La base de datos debería estar accesible solo desde la aplicación. Nunca directamente desde internet.
Flask y MongoDB son herramientas extremadamente ligeras. Esa ligereza es parte de su encanto: puedes construir APIs funcionales con muy poco código.
Pero esa misma libertad significa que muchas decisiones importantes quedan en manos del desarrollador. Organización del proyecto, manejo de credenciales, validación de datos y control de acceso a la base de datos.
No son detalles glamorosos, pero son los que separan un backend improvisado de uno que puede crecer sin romperse en el proceso.
