Docs Menu
Docs Home
/ /

튜토리얼: SQL 에서 MongoDB 로 Flask 마이그레이션

이 튜토리얼에서는 Flask 애플리케이션 SQL 에서 MongoDB 로 마이그레이션 방법을 보여줍니다. 구체적으로 설명하면, 이 튜토리얼에서는 SQLAlchemy를 사용하는 예시 블로그 애플리케이션 Flask- PyMongo 사용하는 애플리케이션으로 변환합니다.

예시 애플리케이션 다음과 같은 기능이 포함되어 있습니다.

  • 블로그 게시물 작성, 편집 및 보기

  • 블로그 게시물 검색

MongoDB 는 데이터를 문서에 저장하는 NoSQL 데이터베이스 입니다. 다음 목록에서는 주요 MongoDB 개념에 대해 설명합니다.

  • 컬렉션: SQL 데이터베이스의 테이블과 유사한 문서 그룹입니다. 컬렉션은 스키마 시행하다 하지 않습니다.

  • 문서: 데이터를 저장 JSON 과 유사한 객체입니다. 문서에는 배열과 중첩된 하위 문서가 포함될 수 있습니다.

  • BSON: MongoDB 내부적으로 사용하는 바이너리 JSON 형식입니다. BSON 날짜 및 바이너리와 같은 추가 데이터 유형으로 JSON 확장합니다.

다음 표에서는 MongoDB 와 SQL 데이터베이스를 비교합니다.

기능
SQL
MongoDB

스키마

사전 정의된 테이블과 열로 고정된 스키마 적용합니다.

동적 데이터 모델을 허용하는 유연한 스키마

데이터 구조

행과 열이 있는 테이블에 데이터를 저장합니다.

문서 컬렉션에 데이터를 저장합니다.

관계

외래 키와 조인을 사용하여 테이블 간의 관계를 설정합니다.

조인 없이 다른 문서 내에 문서를 포함하거나 참조할 수 있습니다.

쿼리 언어

구조화된 쿼리 언어(SQL) 사용

풍부한 JSON 기반 쿼리 언어 사용

이 튜토리얼에서는 다음 단계를 완료하는 방법을 보여줍니다.

  • 전제 조건 확인

  • Flask 설치 - PyMongo

  • Flask 애플리케이션 모델 업데이트

  • Flask 애플리케이션 구성 업데이트

  • Flask 애플리케이션 경로 업데이트

  • SQLite에서 데이터 내보내기

  • MongoDB 로 데이터 가져오기

  • Flask 템플릿 업데이트

  • 마이그레이션된 애플리케이션 실행

1

이 튜토리얼에는 다음과 같은 전제 조건이 필요합니다.

  • 로컬 머신에 MongoDB 설치되어 있어야 합니다. 자세한 내용은 MongoDB Server 매뉴얼의 MongoDB 설치 가이드 참조하세요.

  • SQLAlchemy를 사용하는 기존 Flask 애플리케이션 입니다. 이 튜토리얼에서는 GitHub의 flask-mongo 리포지토리 에 있는 예시 Flask 애플리케이션 사용할 수 있습니다.

  • Python 3.7 이상.

flask-mongo 예시 애플리케이션 flask-mongoflask-sql라는 두 개의 하위 폴더가 포함되어 있습니다. flask-sql 폴더에는 이 튜토리얼의 마이그레이션 에 사용할 수 있는 SQLAlchemy를 사용하는 Flask 애플리케이션 포함되어 있습니다.

마이그레이션 시작하기 전에 다음 작업을 완료하세요.

  1. 테이블, 관계, 데이터 유형을 포함한 SQL 데이터베이스 스키마 검토합니다.

  2. MongoDB 에서 특별한 처리가 필요할 수 있는 복잡한 쿼리와 관계를 식별합니다.

  3. 데이터베이스 의 문서 지향적 특성을 고려하여 MongoDB 스키마 설계합니다. MongoDB 의 스키마 설계 에 대해 자세히 학습 MongoDB Server 매뉴얼의 스키마 설계 가이드 를 참조하세요.

  4. 현재 SQL 데이터베이스 의 전체 백업 만듭니다.

2

Flask- PyMongo 는 MongoDB Flask 애플리케이션과 통합하는 Flask 확장 프로그램입니다.

다음 명령을 실행 하여 Flask- PyMongo 설치합니다.

pip install Flask-PyMongo Flask
3

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
}
@staticmethod
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__: 게시 의 문자열 표현을 반환합니다.

4

__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- PyMongo 확장을 통해 MongoDB 사용하도록 Flask 애플리케이션 초기화합니다.

다음 코드를 추가하여 MongoDB 설정을 포함하도록 config.py 파일 업데이트합니다.

import os
class Config:
SECRET_KEY = os.urandom(24)
MONGO_URI = 'mongodb://localhost:27017/blogdb'

manage.py 파일 삭제합니다. 이 파일 MongoDB 에는 적용 되지 않는 SQL 의 데이터베이스 마이그레이션에 사용됩니다.

참고

MongoDB 에 대한 마이그레이션이 필요한 경우 Beanie ODM이 마이그레이션 지원 제공합니다.

5

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
@app.route("/")
@app.route("/home")
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)
@app.route("/post/new", methods=["GET", "POST"])
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)
@app.route("/post/<post_id>")
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)
@app.route("/post/<post_id>/edit", methods=["GET", "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)
@app.route("/post/<post_id>/delete", methods=["POST"])
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"))
@app.route("/search", methods=["GET", "POST"])
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의 정규식 기능을 사용하여 게시물 검색

6

새 파일 에 다음 코드를 추가하여 SQLite 데이터베이스 의 모든 테이블을 나열하는 export_list_tables.py 이라는 이름의 Python 스크립트 만듭니다.

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 테이블이 표시됩니다.

새 파일 에 다음 코드를 추가하여 export_to_json.py 이라는 이름의 다른 Python 스크립트 만들어 데이터를 JSON 으로 내보냅니다.

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 형식으로 내보낸 데이터가 포함되어 있습니다.

7

새 파일 에 다음 코드를 추가하여 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 처음 데이터를 쓰기 (write) 때 데이터베이스 자동으로 생성합니다.

8

post_id=post.id 의 모든 인스턴스를 post_id=post._id로 변경하여 MongoDB 문서 ID 사용하도록 템플릿 파일을 업데이트합니다.

9

다음 명령을 실행 하여 Flask 애플리케이션 실행합니다.

python run.py

웹 브라우저에서 http://127.0.0.1:5000/home (으)로 이동하여 애플리케이션 액세스 할 수 있습니다.

Flask-Pymongo에 대해 자세히 학습 Flask- PyMongo 설명서를 참조하세요.

돌아가기

튜토리얼: Azure Container Apps에 Flask 앱 배포

이 페이지의 내용