Flask+mysqlの環境をザックリ作ってみる
自分用に備忘録になります。Flaskからmysqlを動かそうとしている方には参考になるかもしれません。
前準備
venvで仮想環境を作成し、必要なモジュールをインストールしておきます。
今回使用したのは以下のモジュールです。
Flask
flask-sqlalchemy
PyMySQL
python-dotenv
python -m venv flasktest
# 仮想環境をアクティブ状態に
.\flasktest\Scripts\activate
# アクティブ状態で各インストールを進める
pip install Flask flask-sqlalchemy PyMySQL python-dotenv
python-dotenvを使用してDB接続情報を.envに切り出すためプロジェクトのルートディレクトリ直下に.envファイルを作成して以下のように記述しました。こちらは各環境に合わせてください。
DB_USER = "root"
DB_PASS = "admin"
DB_HOST = "localhost"
DB_NAME = "fltest"
ディレクトリ構成
今回は以下のような構成になっています。
[プロジェクトのルートディレクトリ]
flasktest (venvで作成したファイル)
.env (python-dotenvで切り出した環境変数のファイル)
templates (後述で作成するhtmlファイルのフォルダ)
hello.html (後述で作成するhtmlファイル)
app.py (後述で作成するPythonファイル)
Pythonファイルの作成
今回は簡単にルートディレクトリにアクセスがあった場合にDBのSELECT結果を持たせてhello.htmlを表示するようにします。全文は以下のようになりました。
上からザックリ説明を書くと、load_dotenv()で.envファイルから環境変数を読み込み、app.configの箇所でmysqlの接続情報を設定。Python側で使用するテーブルの定義を記載することでテーブルの情報をPythonの記法で扱えるように紐づけを行っており、最後にFlaskの手法でSELECT結果をhello.htmlに渡しています。
from flask import Flask
from flask import render_template
from flask_sqlalchemy import SQLAlchemy
from dotenv import load_dotenv
import os
load_dotenv()
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = \
"mysql+pymysql://{user}:{password}@{host}/{dbName}?charset=utf8".format(
user = os.getenv('DB_USER'),
password = os.getenv('DB_PASS'),
host = os.getenv('DB_HOST'),
dbName = os.getenv('DB_NAME')
)
db = SQLAlchemy(app)
class Kakeibo(db.Model):
__tablename__ = "kakeibo"
id = db.Column(db.Integer, primary_key = True, autoincrement=True)
genre = db.Column(db.Integer)
title = db.Column(db.String(255))
price = db.Column(db.Numeric(10,2))
purchase_date = db.Column(db.Date)
with app.app_context():
db.create_all()
@app.route('/')
def hello():
Kakeibos = Kakeibo.query.all()
print(Kakeibos)
return render_template('hello.html',Kakeibos = Kakeibos)
htmlファイルの作成
今回は特に凝ったことはせずSELECT結果から特定のカラムを画面上に表示しています。Flaskなのでjinjaを用いてfor文を書き、マスタッシュ内で表示したいオブジェクトの名称を記載しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>sample hello</title>
</head>
<body>
<ul>
{% for kakeibo in Kakeibos %}
<li>{{ kakeibo.id, kakeibo.title }}</li>
{% endfor %}
</ul>
</body>
</html>
詰まった点
Pythonの中でテーブルの定義を記載していますがmysqlの型と同じ名称ではないのでその点を注意して記載する必要がありそうです。
例えばmysqlではDECIMAL(10, 2)となっている箇所をpython内ではNumeric(10,2)と書く必要がありました。
今回は1テーブルだけなので実行ファイル内に直接定義を記載しましたが、規模が大きくなる場合は他ファイルに切り出す必要がありそうですし、テーブル数が多い場合はメンテナンスも大変そうだなと感じました。(mysqlを直接使うことには慣れている方でもSQLAlchemyを使ったことが無い方はいらっしゃると思うので学習コスト面に関してもそうですね。実際の大規模PJではどのように運用しているのか気になります。)