DB에 있는 정보를 파이썬 코드 속에서 SQL raw Query를 통해 정보를 가져오는 아래와 같은 코드의 형태는 대다수의 언어에서 지원합니다.
1 2 3 4 5 6 7
import sqlite3
# 굳이 sqlite3이 아닌 다른 MySQL와 같은 DB의 connect를 이뤄도 상관없습니다. # 여기서는 파이썬 파일과 같은 위치에 blog.sqlite3 파일이 있다고 가정합니다. conn = sqlite3.connect("blog.sqlite3") cur = conn.cursor() cur.execute("select * from post where id < 10;")
위와 같은 형식으로 코드를 사용할 경우 웹이 이루어지는 과정 중 2~3번째 과정인 “SQL쿼리 요청하기”와 “데이터 받기”라는 부분을 수동으로 처리해 줘야 하는 부분이 있습니다.
이런 경우 파이썬 파일이더라도 한 파일 안에 두개의 언어를 사용하게 되는 셈입니다. (python와 SQL)
만약 여러분이 Pandas DataFrame객체를 DB에서 가져와 만들려면 이런 문제가 생깁니다.
from datetime import datetime from flask import Flask, jsonify from flask_sqlalchemy import SQLAlchemy import pandas as pd import json
app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.sqlite3' db = SQLAlchemy(app)
classPost(db.Model): __tablename__ = 'post'
id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100)) content = db.Column(db.Text) pub_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
# 아래 줄을 추가해 줍시다. # List post which id is less then 10 @app.route('/') defpost_all(): df = pd.read_sql_query("select * from post where id < 10;", db.session.bind).to_json() return jsonify(json.loads(df))
자, 분명히 ORM을 쓰는데도 아직 SQL 쿼리를 쓰고있네요! SQL쿼리문을 지워버립시다!
queryset 객체를 만들기
우리는 Post라는 모델을 만들어줬으니 이제 Post객체의 .query와 .filter()를 통해 객체들을 가져와 봅시다.
우선 queryset라는 이름에 넣어줍시다. 그리고 Pandas의 read_sql(유의: read_sql_query가 아닙니다.)에 queryset의 내용과 세션을 넘겨줘 DataFrame 객체로 만들어줍시다.
from datetime import datetime from flask import Flask, jsonify from flask_sqlalchemy import SQLAlchemy import pandas as pd import json
app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.sqlite3' db = SQLAlchemy(app)
classPost(db.Model): __tablename__ = 'post'
id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100)) content = db.Column(db.Text) pub_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
# List post which id is less then 10 @app.route('/') defpost_all(): # 이 줄은 지우고, # df = pd.read_sql_query("select * from post where id < 10;", db.session.bind).to_json() # 아래 두줄을 추가해주세요. queryset = Post.query.filter(Post.id < 10) # SQLAlchemy가 만들어준 쿼리, 하지만 .all()이 없어 실행되지는 않음 df = pd.read_sql(queryset.statement, queryset.session.bind) # 진짜로 쿼리가 실행되고 DataFrame이 만들어짐 return jsonify(json.loads(df).to_json())
자, 위와 같이 코드를 짜 주면 이제 SQLAlchemy ORM와 Pandas의 read_sql을 통해 df이 DataFrame 객체로 자연스럽게 가져오게 됩니다.
정리하기
여러분이 Pandas를 사용해 데이터를 분석하거나 정제하려 할 때 웹앱으로 Flask를 사용하고 ORM을 이용한다면, 굳이 SQL Query를 직접 만드는 대신 이처럼 Pandas와 SQLAlchemy의 강력한 조합을 이용해 보세요. 조금 더 효율적인 시스템 활용을 고려한 파이썬 프로그램이 나올거에요!
TL;DR
아래 코드와 같이 모델을 만들고 db 객체를 만든 뒤 pandas의 read_sql을 사용하면 됩니다.
from datetime import datetime from flask import Flask, jsonify from flask_sqlalchemy import SQLAlchemy import pandas as pd import json
app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.sqlite3' db = SQLAlchemy(app)
classPost(db.Model): __tablename__ = 'post'
id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100)) content = db.Column(db.Text) pub_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
# List post which id is less then 10 @app.route('/') defpost_all(): queryset = Post.query.filter(Post.id < 10) # SQLAlchemy가 만들어준 쿼리, 하지만 .all()이 없어 실행되지는 않음 df = pd.read_sql(queryset.statement, queryset.session.bind) # 진짜로 쿼리가 실행되고 DataFrame이 만들어짐 return jsonify(json.loads(df).to_json())