Overview
このチュートリアルでは、FlaskアプリケーションをSQLからMongoDBに移行する方法を説明します。具体的には、このチュートリアルでは、SQLAlchemy を使用する例のブログアプリケーションを、Flask- PyMongo を使用するものに変換します。
この例アプリケーションには、次の機能が含まれています。
ブログ投稿の作成、編集、表示
ブログ記事の検索
MongoDBの理解
MongoDBは、ドキュメントにデータを保存する NoSQLデータベースです。以下のリストでは、 MongoDB の主要な概念を説明しています。
コレクション: SQLデータベースのテーブルに似たドキュメントのグループ。スキーマを強制しません。
ドキュメント: データを保存するJSONのようなオブジェクト。ドキュメントには配列やネストされたサブドキュメントを含めることができます。
BSON : MongoDB が内部的に使用するバイナリJSON形式。 BSON は、日付やバイナリなどの追加のデータ型でJSONを拡張したものです。
次の表は、 MongoDBデータベースとSQLデータベースを比較したものです。
機能 | SQL | MongoDB |
|---|---|---|
スキーマ | 事前定義されたテーブルと列を含む固定スキーマを強制 | 動的データモデルを可能にする柔軟なスキーマ |
データ構造 | 行と列を含むテーブルにデータを保存 | ドキュメントのコレクションにデータを保存 |
関係 | テーブル間の関係を確立するために外部キーと結合を使用します | ドキュメントを他のドキュメントに埋め込みます。または参照します。結合は必要ありません |
クエリ言語 | 構造化クエリ言語の使用(SQL) | 豊富なJSONベースのクエリ言語を使用 |
Tutorial
このチュートリアルでは、次の手順を実行する方法について説明します。
前提条件を確認します
フラグのインストール- PyMongo
[Flask]アプリケーションモデルを更新します
[Flask]アプリケーション構成を更新します
[Flask]アプリケーションルートを更新します
SQLite からのデータのエクスポート
MongoDBへのデータのインポート
[Flask] テンプレートを更新します
移行したアプリケーションの実行
前提条件を確認します
このチュートリアルには次の前提条件が必要です。
MongoDB はローカルマシンにインストールされています。手順については、 MongoDB Serverマニュアルの MongoDBのインストールガイドを参照してください。
SQLAlchemy を使用する既存の Fluskアプリケーション。このチュートリアルでは、GitHub の fluk-mongoリポジトリの例フラグアプリケーションを使用できます。
Python 3.7 以降。
flask-mongo例アプリケーションには、flask-mongo と flask-sql の 2 つのサブフォルダが含まれています。 flask-sql フォルダーには、このチュートリアルの移行に使用できる SQLAlchemy を使用する Flukアプリケーションが含まれています。
移行を開始 する前に、次のアクションを完了してください。
[Flask]アプリケーションモデルを更新します
models.pyファイルの内容を次のコードで置き換えます。
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}')"
このコードでは、 MongoDBのブログ投稿をモデル化する Postクラスを定義します。クラスには、次のメソッドが含まれています。
__init__: 各書き込みのタイトル、内容、書き込み日付、一意の識別子を設定to_dict:インスタンスをMongoDBストレージの辞書に変換from_dict: 辞書からPostインスタンスを作成します__repr__: 書き込みの string 表現を返します
[Flask]アプリケーション構成を更新します
__init__.pyファイルの内容を次のコードで置き換えます。
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
このコードは、Flaskアプリケーションを初期化し、Flask- PyMongo拡張機能を通じてMongoDBを使用するようにします。
次のコードを追加して、 MongoDB設定を含むように config.pyファイルをアップデートします。
import os class Config: SECRET_KEY = os.urandom(24) MONGO_URI = 'mongodb://localhost:27017/blogdb'
manage.pyファイルを削除します。このファイルはSQLのデータベース移行に使用しますが、 MongoDBには適用されません。
[Flask]アプリケーションルートを更新します
routes.pyファイルの内容を次のコードで置き換えます。
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)
このコードでは、SQLAlchemy の代わりにMongoDBを使用するようにルートを更新します。ルートは次のアクションを完了します。
MongoDBでのストレージに
to_dictメソッドを使用して、Postインスタンスを辞書に変換する次を使用して投稿を取得する
mongo.db.posts.find()を使用して投稿を挿入
mongo.db.posts.insert_one()次を使用して投稿を更新します
mongo.db.posts.update_one()次を使用して投稿を削除します
mongo.db.posts.delete_one()MongoDB の正規表現機能を使用して投稿を検索
SQLite からのデータのエクスポート
export_list_tables.py という名前のPythonスクリプトを作成し、次のコードを新しいファイルに追加して、SQLiteデータベース内のすべてのテーブルを一覧表示します。
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)
このスクリプトを実行して、テーブル名を表示します。出力には post テーブルが表示されます。
データをJSONにエクスポートするには、次のコードを新しいファイルに追加して、export_to_json.py という名前の別のPythonスクリプトを作成します。
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()
次のスクリプトを実行して、現在のディレクトリに post.jsonファイルを作成します。このファイルには、 JSON形式のエクスポートされたデータが含まれています。
MongoDBへのデータのインポート
import_to_mongo.py という名前のPythonスクリプトを作成し、次のコードを新しいファイルに追加して、 JSONファイルをMongoDBにインポートします。
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)
このスクリプトを実行して、データをMongoDBにインポートします。スクリプトはdate_postedフィールドを日時オブジェクトに変換し、すべての投稿をMongoDBコレクションに挿入します。
注意
接続文字列mongodb://localhost:27017/blogdb は、ポート 27017 にあるローカルホスト上のMongoDBインスタンスに接続します。 MongoDB は最初にデータを書き込むと、データベースを自動的に作成します。
追加リソース
[Flask-Pymongo] の詳細については、Flask- PyMongoに関するドキュメントを参照してください。