개요
이 튜토리얼에서는 Flask 애플리케이션 SQL 에서 MongoDB 로 마이그레이션 방법을 보여줍니다. 구체적으로 설명하면, 이 튜토리얼에서는 SQLAlchemy를 사용하는 예시 블로그 애플리케이션 Flask- PyMongo 사용하는 애플리케이션으로 변환합니다.
예시 애플리케이션 다음과 같은 기능이 포함되어 있습니다.
블로그 게시물 작성, 편집 및 보기
블로그 게시물 검색
MongoDB 이해
MongoDB 는 데이터를 문서에 저장하는 NoSQL 데이터베이스 입니다. 다음 목록에서는 주요 MongoDB 개념에 대해 설명합니다.
컬렉션: SQL 데이터베이스의 테이블과 유사한 문서 그룹입니다. 컬렉션은 스키마 시행하다 하지 않습니다.
문서: 데이터를 저장 JSON 과 유사한 객체입니다. 문서에는 배열과 중첩된 하위 문서가 포함될 수 있습니다.
BSON: MongoDB 내부적으로 사용하는 바이너리 JSON 형식입니다. BSON 날짜 및 바이너리와 같은 추가 데이터 유형으로 JSON 확장합니다.
다음 표에서는 MongoDB 와 SQL 데이터베이스를 비교합니다.
기능 | SQL | MongoDB |
|---|---|---|
스키마 | 사전 정의된 테이블과 열로 고정된 스키마 적용합니다. | 동적 데이터 모델을 허용하는 유연한 스키마 |
데이터 구조 | 행과 열이 있는 테이블에 데이터를 저장합니다. | 문서 컬렉션에 데이터를 저장합니다. |
관계 | 외래 키와 조인을 사용하여 테이블 간의 관계를 설정합니다. | 조인 없이 다른 문서 내에 문서를 포함하거나 참조할 수 있습니다. |
쿼리 언어 | 구조화된 쿼리 언어(SQL) 사용 | 풍부한 JSON 기반 쿼리 언어 사용 |
튜토리얼
이 튜토리얼에서는 다음 단계를 완료하는 방법을 보여줍니다.
전제 조건 확인
Flask 설치 - PyMongo
Flask 애플리케이션 모델 업데이트
Flask 애플리케이션 구성 업데이트
Flask 애플리케이션 경로 업데이트
SQLite에서 데이터 내보내기
MongoDB 로 데이터 가져오기
Flask 템플릿 업데이트
마이그레이션된 애플리케이션 실행
전제 조건 확인
이 튜토리얼에는 다음과 같은 전제 조건이 필요합니다.
로컬 머신에 MongoDB 설치되어 있어야 합니다. 자세한 내용은 MongoDB Server 매뉴얼의 MongoDB 설치 가이드 참조하세요.
SQLAlchemy를 사용하는 기존 Flask 애플리케이션 입니다. 이 튜토리얼에서는 GitHub의 flask-mongo 리포지토리 에 있는 예시 Flask 애플리케이션 사용할 수 있습니다.
Python 3.7 이상.
flask-mongo 예시 애플리케이션 flask-mongo 및 flask-sql라는 두 개의 하위 폴더가 포함되어 있습니다. flask-sql 폴더에는 이 튜토리얼의 마이그레이션 에 사용할 수 있는 SQLAlchemy를 사용하는 Flask 애플리케이션 포함되어 있습니다.
마이그레이션 시작하기 전에 다음 작업을 완료하세요.
테이블, 관계, 데이터 유형을 포함한 SQL 데이터베이스 스키마 검토합니다.
MongoDB 에서 특별한 처리가 필요할 수 있는 복잡한 쿼리와 관계를 식별합니다.
데이터베이스 의 문서 지향적 특성을 고려하여 MongoDB 스키마 설계합니다. MongoDB 의 스키마 설계 에 대해 자세히 학습 MongoDB Server 매뉴얼의 스키마 설계 가이드 를 참조하세요.
현재 SQL 데이터베이스 의 전체 백업 만듭니다.
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__: 게시 의 문자열 표현을 반환합니다.
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- 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이 마이그레이션 지원 제공합니다.
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에서 데이터 내보내기
새 파일 에 다음 코드를 추가하여 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 형식으로 내보낸 데이터가 포함되어 있습니다.
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 처음 데이터를 쓰기 (write) 때 데이터베이스 자동으로 생성합니다.
추가 리소스
Flask-Pymongo에 대해 자세히 학습 Flask- PyMongo 설명서를 참조하세요.