Flask + MySQL(Docker)環境でDB接続
GoalFlask + MySQL環境を構築してpythonスクリプトでデータベースからユーザー情報を抜き出しブラウザに表示する。
ディレクトリ構成:
app
|---templates
|---index.html
index.py
Dockerfile
docker-compose.yaml
Dockerfile:
FROM python:3.9
WORKDIR /app
COPY ./app /app
RUN pip install Flask
RUN pip install -U PyMySQL #今回使うモジュール(DBエンジン)
CMD ["python", "index.py"]
docker-compose.yaml
※コンテナ間で通信を行うときに何も設定しないと接続できない事象が生じた。networksの部分の設定を行うことで解消。また記事に出します。
version: '3'
services:
db:
image: mysql:8.0
platform: linux/x86_64
environment:
MYSQL_ROOT_PASSWORD: password
ports:
- '3306:3306'
command: --default-authentication-plugin=mysql_native_password
networks:
- app-net
flask:
build: .
ports:
- "5005:80"
networks:
- app-net
depends_on:
- db
networks:
app-net:
driver: bridge
index.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template('index.html')
if __name__ == "__main__":
app.run(host="0.0.0.0", port=80, debug=True)
index.htmlはテキトーにhtmlファイル書いといてといてくれ。。
とりあえずこれで基本的な設定は終わった。コンテナ立ち上げて、ブラウザからアクセスするとindex.htmlファイルの内容がレンダリングされる。
-------------------------------ここから本番--------------------------------
本当は一緒にログイン機能を実装したいが今回は手動でDBにユーザーを作って、URLから指定されたユーザの情報をそのまま認証なしに抜き出して表示するところまで行う。
0.0.0.0:5005/user/1にアクセスしたときに、
user_id: 1
name: ”達郎”
birthday: 2001-09-09
club: "soccer"
これくらいの情報をブラウザに表示できることがゴールかな。
1. DBサーバーに入り込んで新しいデータベースとテーブルを作って、その中にユーザーを登録する
docker exec -it mysql_container_id bash
mysql -u root -p
mysql>CREATE DATABASE main; mainデータベースを作成
mysql> use main
mysql>CREATE TABLE user (id INT, name CHAR(20), birthday DATE, club CHAR(20));
これでuserテーブルを作れたので、データを挿入していく。とりあえず2つ。
INSERT INTO user (id, name, birthday, club) VALUES (1, "Tatsuro", '2001-09-09', 'soccer');
INSERT INTO user (id, name, birthday, club) VALUES (2, "Ito", '1990-12-02', 'basketball');
こんな感じで登録されているのを確認する。
mysql> SLECT * FROM user;
+------+---------+------------+------------+
| id | name | birthday | club |
+------+---------+------------+------------+
| 1 | Tatsuro | 2001-09-09 | soccer |
| 2 | Ito | 1990-12-02 | basketball |
+------+---------+------------+------------+
2 rows in set (0.01 sec)
2.DBへの接続コード記述
index.pyと同じ階層にmodel.pyを作成する(ここで、DBへの接続、データの取得を行う)
model.py
import pymysql.cursors
def get_user_info(id):
connect = pymysql.connect(host='flask-mysql_db_1',
port=3306,
password='password',
user='root',
db='main',
cursorclass=pymysql.cursors.DictCursor)
with connect.cursor() as cursor:
sql = "SELECT * FROM user WHERE id = " + id
cursor.execute(sql)
results = cursor.fetchall()
connect.close()
return results
3.DBへの接続ファイルmodel.pyをモジュールとしてindex.pyに取り込む。
import modelでmodel.pyを読み込んで、model.pyの中で定義されているメソッドであるget_user_info(id)はレスポンスとしてidによって指定されたuserの情報を吐き出すようにしているので、index.pyから呼び出したとき、そのレスポンスの中身(user_info)の中にはidで指定したユーザー情報が入っている。
index.py
from flask import Flask, render_template
from markupsafe import escape
import model
app = Flask(__name__)
@app.route("/")
def index():
return render_template('index.html')
@app.route("/user/<id>")
def user(id):
user_info = model.get_user_info(id)
return f"{user_info}"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=80, debug=True)
今のままだと、0.0.0.0/5005/user/1にアクセスすると
こんなかんじで返ってくる。
これをhtmlファイルに整形して組み込んでいく。
4.htmlファイルにユーザー情報を渡して表示
こんな感じで書き換える。htmlファイルへ変数を渡す時はrender_templateの2個目の引数にindex.py内の変数名をhtmlファイルで使用する変数名に代入する形で渡すことができる。今回はuser_infoをuserという変数に入れuser.htmlファイルで使用できるようにしている。
index.py
@app.route("/user/<id>")
def user(id):
user_info = model.get_user_info(id)
return render_template('user.html', user=user_info[0])
user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>User</h1>
<ul>
<li>{{ user.id }}</li>
<li>{{ user.name }}</li>
<li>{{ user.birthday }}</li>
<li>{{ user.club }}</li>
</ul>
</body>
</html>
こんな感じでユーザー情報を表示できた。
Discussion