Overview
Este tutorial muestra cómo migrar una aplicación Flask de SQL a MongoDB. En concreto, convierte una aplicación de blog de ejemplo que usa SQLAlchemy en una que usa Flask-PyMongo.
La aplicación de ejemplo incluye las siguientes características:
Crear, editar y visualizar publicaciones de blog
Buscando publicaciones 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: Grupos de documentos, similares a las tablas de bases de datos SQL. Las colecciones no imponen un esquema.
Documentos: Objetos tipo JSON que almacenan datos. Pueden contener matrices y subdocumentos anidados.
BSON: Formato JSON binario que MongoDB utiliza internamente. BSON amplía JSON con tipos de datos adicionales, como fecha y binario.
La siguiente tabla compara las bases de datos MongoDB y SQL:
Característica | 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 |
Relaciones | Utiliza claves externas y uniones para establecer relaciones entre tablas | Incrusta documentos dentro de otros documentos o hace referencia a ellos, sin necesidad de uniones |
languaje del query | Utiliza lenguaje de consulta estructurado (SQL) | Utiliza un rico lenguaje de consulta basado en JSON |
Tutorial
Este tutorial le muestra cómo completar los siguientes pasos:
Verificar los prerrequisitos
Instalar Flask-PyMongo
Actualizar los modelos de aplicación de Flask
Actualizar la configuración de la aplicación Flask
Actualizar las rutas de la aplicación Flask
Exportar datos desde SQLite
Importar datos a MongoDB
Actualizar las plantillas de Flask
Ejecutar la aplicación migrada
Verificar los prerrequisitos
Este tutorial requiere los siguientes requisitos previos:
MongoDB instalado en su equipo local. Consulte la Consulte la guía de instalación de MongoDB en el manual del servidor MongoDB para obtener instrucciones.
Una aplicación Flask existente que usa SQLAlchemy. Puedes usar la aplicación Flask de ejemplo del repositorio flask-mongo en GitHub para este tutorial.
Python 3.7 o posterior.
El 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 usa SQLAlchemy, que puede usar para la migración de este tutorial.
Antes de comenzar la migración, complete las siguientes acciones:
Revise el esquema de su base de datos SQL, incluidas las tablas, las relaciones y los tipos de datos.
Identifique consultas y relaciones complejas que podrían requerir un manejo especial en MongoDB.
Diseñe su esquema de MongoDB considerando la naturaleza documental de la base de datos. Para obtener más información sobre el diseño de esquemas en MongoDB, consulte la guía "Diseño de esquemas" en el manual de MongoDB Server.
Cree una copia de seguridad completa de su base de datos SQL actual.
Actualizar los modelos de aplicación de 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 para cada publicación.to_dict:Convierte una instancia en un diccionario para el almacenamiento de MongoDBfrom_dict: Crea una instanciaPosta partir de un diccionario__repr__: Devuelve una representación de cadena de la publicación.
Actualizar 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.
Actualice su archivo config.py para incluir la configuración de MongoDB agregando el siguiente código:
import os class Config: SECRET_KEY = os.urandom(24) MONGO_URI = 'mongodb://localhost:27017/blogdb'
Elimine el archivo manage.py. Este archivo se utiliza para migraciones de bases de datos en SQL, lo cual no aplica a MongoDB.
Nota
Si necesita migraciones para MongoDB,Beanie ODM proporciona soporte para migración.
Actualizar 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:
Convierta instancias
Posten diccionarios utilizando el métodoto_dictpara el almacenamiento en MongoDBRecuperar publicaciones mediante
mongo.db.posts.find()Insertar publicaciones mediante
mongo.db.posts.insert_one()Actualizar publicaciones mediante
mongo.db.posts.update_one()Eliminar publicaciones mediante
mongo.db.posts.delete_one()Buscar publicaciones utilizando las capacidades de expresiones regulares de MongoDB
Exportar datos desde SQLite
Cree un script de Python llamado export_list_tables.py para enumerar todas las tablas en su base de datos SQLite agregando el siguiente código a un nuevo archivo:
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)
Ejecute este script para mostrar los nombres de las tablas. El resultado 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 nuevo archivo:
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()
Ejecute este script para crear el archivo post.json en el directorio actual. Este archivo contiene los datos exportados en formato JSON.
Importar datos a MongoDB
Cree un script de Python llamado import_to_mongo.py para importar el archivo JSON a MongoDB agregando 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)
Ejecute este script para importar sus datos a MongoDB. El script convierte el campo date_posted en un objeto de fecha y hora e inserta todas las publicaciones en la colección de MongoDB.
Nota
La cadena de conexión mongodb://localhost:27017/blogdb se conecta a su instancia de MongoDB en el host local, en el puerto 27017. MongoDB crea la base de datos automáticamente al escribir datos por primera vez.
Recursos adicionales
Para obtener más información sobre Flask-Pymongo, consulte la documentación de Flask-PyMongo.