Overview
Este tutorial te muestra cómo migrar una aplicación Flask de SQL a MongoDB. Específicamente, el tutorial convierte una aplicación de blog de ejemplo que utiliza SQLAlchemy en una que utiliza Flask-PyMongo.
La aplicación de ejemplo incluye las siguientes funcionalidades:
Creación, edición y visualización de entradas de blog
Buscando entradas de blog
Entendiendo MongoDB
MongoDB es una base de datos NoSQL que almacena datos en documentos. La siguiente lista describe los conceptos clave de MongoDB:
Colecciones: Es un grupo de documentos, similares a tablas en bases de datos SQL. Las colecciones no aplican un esquema.
Documentos. Objetos similares a JSON que almacenan datos. Los documentos pueden contener arreglos y subdocumentos anidados.
BSON: formato JSON binario que MongoDB utiliza internamente. BSON amplía JSON con tipos de datos adicionales como Date y Binary.
La siguiente tabla compara MongoDB y las bases de datos SQL:
funcionalidad | SQL | MongoDB |
|---|---|---|
Esquema | Aplica un esquema fijo con tablas y columnas predefinidas | Esquemas flexibles que permiten modelos de datos dinámicos |
Estructura de datos | Almacena datos en tablas con filas y columnas | Almacena datos en colecciones de documentos |
relación | Utiliza claves externas y uniones para establecer relaciones entre tablas | Incorpora documentos en otros documentos o los referencia, sin necesidad de uniones |
languaje del query | Utiliza Structured Query Language (SQL) | Emplea un languaje del query amplio basado en JSON |
Tutorial
Este tutorial le muestra cómo completar los siguientes pasos:
Verifique los requisitos previos
Instalar Flask-PyMongo
Actualizar los modelos de la aplicación Flask
Actualiza la configuración de la aplicación Flask
Actualiza las rutas de la aplicación Flask
Exporta los datos desde SQLite
Importa datos en MongoDB
Actualizar las plantillas de Flask
Ejecutar la aplicación migrada
Verifique los requisitos previos
Este tutorial requiere los siguientes requisitos previos:
MongoDB instalado en su máquina local. Consulta la Guía de Instalación de MongoDB en el manual del MongoDB Server para obtener instrucciones.
Una aplicación Flask existente que utiliza SQLAlchemy. Puedes utilizar la aplicación de ejemplo Flask del flask-mongo repositorio en GitHub para este tutorial.
Python 3.7 o posterior.
La flask-mongo la aplicación de ejemplo contiene dos subcarpetas, flask-mongo y flask-sql. La carpeta flask-sql contiene una aplicación Flask que utiliza SQLAlchemy, que puedes utilizar para la migración en este tutorial.
Antes de comenzar la migración, completa las siguientes acciones:
Revise tu esquema de base de datos SQL, incluidos las tablas, las relaciones y los tipos de datos.
Identificar consultas complejas y relaciones que podrían requerir un tratamiento especial en MongoDB.
Diseña tu esquema de MongoDB considerando la naturaleza orientada a documentos de la base de datos. Para obtener más información sobre el diseño de esquema en MongoDB, consulta la guía Diseña tu esquema en el manual de MongoDB Server.
Cree una copia de seguridad completa de su base de datos SQL actual.
Actualizar los modelos de la aplicación Flask
Reemplace el contenido de su archivo models.py con el siguiente código:
from datetime import datetime from bson.objectid import ObjectId class Post: def __init__(self, title, content, date_posted=None, _id=None): self.title = title self.content = content self.date_posted = date_posted if date_posted \ else datetime.utcnow() self._id = _id if _id else ObjectId() def to_dict(self): return { "title": self.title, "content": self.content, "date_posted": self.date_posted, "_id": self._id } def from_dict(data): return Post( title=data.get('title'), content=data.get('content'), date_posted=data.get('date_posted'), _id=data.get('_id') ) def __repr__(self): return f"Post('{self.title}', \ '{self.date_posted}')"
Este código define una clase Post que modela una entrada de blog para MongoDB. La clase incluye los siguientes métodos:
__init__Establece el título, el contenido, la fecha de publicación y el identificador único de cada publicaciónto_dict: Convierte una instancia en un diccionario para el almacenamiento en MongoDBfrom_dictCrea una instancia dePostdesde un diccionario__repr__: Devuelve una representación de string de la publicación
Actualiza la configuración de la aplicación Flask
Reemplace el contenido de su archivo __init__.py con el siguiente código:
from flask import Flask from flask_pymongo import PyMongo from config import Config app = Flask(__name__) app.config.from_object(Config) mongo = PyMongo(app) from app import routes
Este código inicializa la aplicación Flask para usar MongoDB a través de la extensión Flask-PyMongo.
Actualiza tu archivo config.py para incluir la configuración de MongoDB añadiendo el siguiente código:
import os class Config: SECRET_KEY = os.urandom(24) MONGO_URI = 'mongodb://localhost:27017/blogdb'
Elimina el archivo manage.py. Utilizas este archivo para migraciones de bases de datos en SQL, lo cual no aplica a MongoDB.
Nota
Si necesitas migraciones para MongoDB, el Beanie ODM proporciona soporte para migraciones.
Actualiza las rutas de la aplicación Flask
Reemplace el contenido de su archivo routes.py con el siguiente código:
from flask import render_template, url_for, flash, \ redirect, request from app import app, mongo from bson.objectid import ObjectId from app.models import Post from app.forms import PostForm def home(): posts_data = mongo.db.posts.find() posts = [Post.from_dict(post) for post in posts_data] return render_template("index.html", posts=posts) def new_post(): form = PostForm() if form.validate_on_submit(): post = Post(title=form.title.data, content=form.content.data) mongo.db.posts.insert_one(post.to_dict()) flash("Your post has been created!", "success") return redirect(url_for("home")) return render_template("post.html", title="New Post", form=form) def post(post_id): post_data = mongo.db.posts.find_one_or_404( {"_id": ObjectId(post_id)}) post = Post.from_dict(post_data) return render_template("detail.html", post=post) def edit_post(post_id): post_data = mongo.db.posts.find_one_or_404( {"_id": ObjectId(post_id)}) post = Post.from_dict(post_data) form = PostForm() if form.validate_on_submit(): updated_post = { "$set": {"title": form.title.data, "content": form.content.data} } mongo.db.posts.update_one( {"_id": ObjectId(post_id)}, updated_post) flash("Your post has been updated!", "success") return redirect(url_for("post", post_id=post_id)) elif request.method == "GET": form.title.data = post.title form.content.data = post.content return render_template("edit_post.html", title="Edit Post", form=form) def delete_post(post_id): mongo.db.posts.delete_one({"_id": ObjectId(post_id)}) flash("Your post has been deleted!", "success") return redirect(url_for("home")) def search(): query = request.args.get("query") posts_data = mongo.db.posts.find( { "$or": [ {"title": {"$regex": query, "$options": "i"}}, {"content": {"$regex": query, "$options": "i"}}, ] } ) posts = [Post.from_dict(post) for post in posts_data] return render_template("index.html", posts=posts)
Este código actualiza las rutas para usar MongoDB en lugar de SQLAlchemy. Las rutas realizan las siguientes acciones:
Convierte
Postinstancias en diccionarios utilizando el métodoto_dictpara almacenamiento en MongoDBRecuperar publicaciones usando
mongo.db.posts.find()Insertar publicaciones usando
mongo.db.posts.insert_one()Actualizar publicaciones usando
mongo.db.posts.update_one()Borrar publicaciones utilizando
mongo.db.posts.delete_one()Busca publicaciones usando las capacidades regex de MongoDB
Exporta los datos desde SQLite
Crea un script de Python llamado export_list_tables.py para listar todas las tablas en tu base de datos SQLite agregando el siguiente código a un archivo nuevo:
import sqlite3 # Connect to the SQLite database db_path = 'relative/path/to/site.db' conn = sqlite3.connect(db_path) cursor = conn.cursor() # Query to get all table names cursor.execute("SELECT name FROM sqlite_master WHERE \ type='table';") tables = cursor.fetchall() # Close the connection conn.close() print(tables)
Ejecuta este script para mostrar los nombres de tus tablas. La salida muestra la tabla post.
Cree otro script de Python llamado export_to_json.py para exportar los datos a JSON agregando el siguiente código a un archivo nuevo:
import sqlite3 import json # Connect to the SQLite database db_path = 'relative/path/to/site.db' conn = sqlite3.connect(db_path) cursor = conn.cursor() # Export data from the 'post' table cursor.execute("SELECT * FROM post") rows = cursor.fetchall() # Get the column names column_names = [description[0] for description in \ cursor.description] # Convert to list of dictionaries data = [dict(zip(column_names, row)) for row in rows] # Save to a JSON file with open('post.json', 'w') as f: json.dump(data, f, indent=4) # Close the connection conn.close()
Ejecuta este script para crear el archivo post.json en el directorio actual. Este archivo contiene tus datos exportados en formato JSON.
Importa datos en MongoDB
Crea un script en Python llamado import_to_mongo.py para importar el archivo JSON en MongoDB añadiendo el siguiente código a un nuevo archivo:
from pymongo import MongoClient import json from datetime import datetime def import_json_to_mongo(db_name, collection_name, json_path): client = MongoClient("mongodb://localhost:27017/") db = client[db_name] def convert_date(data): # Update 'date_posted' field to datetime object for item in data: if 'date_posted' in item: item['date_posted'] = datetime.strptime( item['date_posted'], '%Y-%m-%d %H:%M:%S.%f') return data with open(json_path, 'r') as f: data = json.load(f) data = convert_date(data) db[collection_name].insert_many(data) client.close() if __name__ == "__main__": db_name = 'blogdb' collection_name = 'posts' json_path = 'flask-mongo/post.json' import_json_to_mongo(db_name, collection_name, json_path)
Ejecuta este script para importar tus datos a MongoDB. El script convierte el campo date_posted en un objeto datetime e inserta todas las publicaciones en la colección de MongoDB.
Nota
La cadena de conexión mongodb://localhost:27017/blogdb conecta a tu instancia de MongoDB en localhost en el puerto 27017. MongoDB crea la base de datos automáticamente la primera vez que escribes datos.
Recursos adicionales
Para obtener más información sobre Flask-Pymongo, consulta la documentación de Flask-PyMongo.