Entrada
Preview Image

Configuración de Flask con MongoDB de forma segura

Flask: 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.

Esta entrada está licenciada bajo CC BY 4.0 por el autor.