概要
前回 Flask-Migrate でデータベースをマイグレーションしてみました
今回はそのテーブルを使って Flask-SQLAlchemy を使ってデータの CRUD をしてみます
環境
- macOS 10.15.5
- MySQL 8.0.19
- Python 3.8.3
- Flask-SQLAlchemy 2.4.3
準備
必要なライブラリをインストールします
Flask-SQLAlchemy は MySQL に対して操作するので mysqlclient もインストールします
また MySQL から取得したデータをシリアライズするのに Flask-Marshmallow を使います
marshmallow-sqlalchemy は警告が出るのでインストールしているだけなので直接使うことはありません
pipenv install Flask-Marshmallow Flask-SQLAlchemy mysqlclient marshmallow-sqlalchemy
MySQL は事前に起動しておきます
brew services start mysql
なお test データベースの user というテーブルにはすでに以下のデータが入っていることを想定しています
mysql> mysql> select * from user;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | hawk | 10 |
| 2 | hawk | 20 |
+----+------+------+
2 rows in set (0.00 sec)
CRUD するモジュールの作成
各種 SQL を発行するモジュールを作成します
追加や削除に関しては db.session
を使い取得する場合は User.query
を使います
また更新の場合は一度対象のレコードを取り出しモデルにバインドしてから更新したいフィールドを書き換えて再度 db.session.add
する感じになります
vim lib/__init__.py
from my_app import db, User, UserSchema
class CRUD():
def add(self, name, age):
user = User(name=name, age=age)
db.session.add(user)
db.session.commit()
return 'ok'
def select(self):
return UserSchema(many=True).dump(User.query.all())
def _select_one(self, id):
return User.query.get(id)
def delete(self, id):
db.session.delete(self._select_one(id))
db.session.commit()
return 'ok'
def update(self, id, name, age):
user = self._select_one(id)
user.name = name
user.aget = age
db.session.add(user)
db.session.commit()
return 'ok'
今回は 1 つのテーブルに対する操作になりますが複数のテーブルを跨いだリレーションなどを扱う場合ももう少し複雑になります
Flask アプリ側で CRUD をテストするルーティングの追加
Flask アプリの定義やデータベースのマイグレーション処理も含まれているので少し長いです
my_app/__init__.py
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+mysqldb://{}:{}@{}/{}?charset=utf8".format("root", "", "localhost", "test")
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
migrate = Migrate(app, db)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128))
age = db.Column(db.Integer)
ma = Marshmallow(app)
class UserSchema(ma.Schema):
class Meta:
fields = ("id", "name", "age")
@app.route('/add')
def add_user():
name = request.args.get('name')
age = request.args.get('age')
crud = CRUD()
return crud.add(name, age)
@app.route('/select')
def select_user():
crud = CRUD()
return jsonify(crud.select())
@app.route('/delete')
def delete_user():
id = request.args.get('id')
crud = CRUD()
return crud.delete(id)
@app.route('/update')
def update_user():
id = request.args.get('id')
name = request.args.get('name')
age = request.args.get('age')
crud = CRUD()
return crud.update(id, name, age)
from my_app.lib import CRUD # 循環参照になるので最後に import する
route に関しては各 CRUD 処理分定義しています
クエリストリングにしていますが好きな形式でリクエストを受け取れるようにして OK です
UserSchema クラスは SQLAlchemy で取得したデータを json にシリアライズするために追加したクラスです
あとは前回マイグレーションで作成した処理になります
動作確認
では動作確認しましょう
まずはアプリを起動します
FLASK_APP=my_app pipenv run flask run
アプリが起動したら API を叩いてみましょう
curl 'localhost:5000/add?name=test&age=30'
curl 'localhost:5000/select'
curl 'localhost:5000/delete?id=3'
curl 'localhost:5000/update?id=2&name=snowlog&age=99'
最後に
Flask-SQLAlchemy を使って Flask から MySQL に対して簡単な CRUD 処理を行ってみました
エラーハンドリングなど全くしていないのでプロダクトではちゃんと行うようにしてください
正規化をしまくっているデータベースだともっと複雑なクエリを発行することになると思いますが基本的な使い方は理解できるかなと思います
ちょっと書き方的に気になるのが Flask アプリ内にデータベースのモデルを追加しているところです
Flask-Migrate を使う上でそうしていますがもう少し工夫すれば別モジュールとして管理できるかもしれません
0 件のコメント:
コメントを投稿