この記事の目的
DBに対するCRUD操作を行えるwebサーバを作成する。
丁寧に解説しました。
まさかりを歓迎します。
緒言&前提
○前提
・仮のDBとしてlist型を作成し、そこに対してCRUD操作を行います。
仮DBに対する操作を実際のDBに対する操作に書き換えれば良いかと思います。
・python、pip(pythonのパッケージマネージャ)のインストールを前提とします。
○緒言
pythonでwebApiを作成するモチベーションとしては、
・DBデータを数学的に扱うためにnumpyライブラリを使用したいから
というところでしたが、あとから調査してみると、web通信自体はjsなどに任せて、データ処理のみをpython+numpyに任せた方が高速だということでした。
参考:https://qiita.com/KatsunoriNakamura/items/dd567ea7cfaa99685453
言葉
・Flask: python上で動くウェブアプリケーションフレームワーク。かんたんにwebアプリが作れました。
・webApi: この記事では、URIを叩くとDBに対する操作をおこなってくれるwebサーバを指す。
概要
1.Flaskをインストール
2.Apiファイルを作成
1.Flaskをインストール
コマンドラインから、以下のコマンドを打ちます。
pip install Flask
2.Apiファイルを作成
説明の流れとして、まずコード全体を示したあとに、簡単に各コードの解説していきます。
webAPIファイルの全貌
以下のファイルを作成し、実行することでサーバが起動します。
サーバ起動中に、CRUDメソッドに設定したURIを叩くことで、DBを操作できます。
from flask import Flask, jsonify, request, render_template
app = Flask(__name__)
# DB
stores = [
{
'name': 'my_store',
'items': [
{
'name': 'chocolate',
'price': 120
}
]
}
]
# storeに対するCRUD--------------
# GET /store/<string:name>
@app.route('/stores/<string:name>') # 'http://127.0.0.1:5000/store/some_name'
def get_store(name):
for store in stores:
if store["name"] == name:
return jsonify(store)
return jsonify({"message": "no store named {} found.".format(name)})
# POST /store data: {name:}
@app.route('/stores', methods=['POST'])
def create_store():
request_data = request.get_json()
store = next(filter(lambda x: x["name"]==request_data["name"], stores), None)
if store != None:
return jsonify({"message": "store named {} already exist.".format(request_data["name"])})
else:
new_store = {
"name": request_data["name"],
"items": request_data["items"]
}
stores.append(new_store)
return jsonify({"message": "{} store is added.".format(request_data["name"])})
# PUT /store data: {name:}
@app.route('/stores/<string:name>', methods=['PUT'])
def update_store(name):
request_data = request.get_json()
store = next(filter(lambda x: x["name"] == name, stores), None)
if store == None:
return jsonify({"message": "no store named {} found.".format(name)})
else:
store["items"] = request_data["items"]
return jsonify({"message": "{} is updated.".format(name)})
# DELETE /stores/<string:name>
@app.route('/stores/<string:name>', methods=['DELETE'])
def delete_store(name):
global stores
stores = list(filter(lambda x: x["name"] != name, stores))
return jsonify({"message": "Delete store named {}".format(name)})
# --------------------storeに対するCRUD
# GET /stores
@app.route('/stores')
def get_stores():
return jsonify({'stores': stores})
# ホーム画面にhtmlを読み込んでみる。
# GET /
@app.route('/')
def home():
return render_template("index.html")
app.run(port=5000)
解説
from flask import Flask, jsonify, request, render_template
Flaskライブラリから必要なモジュールをインポートしています。
app = Flask(__name__)
アプリケーション本体を作成します。
pythonでは、アンダースコアでかこまれた特別なデフォルト変数があり、nameはファイル名にあたりますので、今回の場合sampleappにあたります。
ただし、実行ファイル(ターミナルからpython ~で実行したファイル)のnameはmainを返します。
Flaskは実行ファイル上でしか正しく動作することができないため、呼び出されたファイルについてname=mainであることを確認しています。
# DB
stores = [
{
'name': 'my_store',
'items': [
{
'name': 'chocolate',
'price': 120
}
]
}
]
仮のDBです。
ストアが複数格納され、各ストアはストア名と複数の商品データがはいるとしています。
# GET /store/<string:name>
@app.route('/stores/<string:name>') # 'http://127.0.0.1:5000/store/some_name'
def get_store(name):
for store in stores:
if store["name"] == name:
return jsonify({"stores": store})
return jsonify({"message": "no store named {} found.".format(name)})
GETメソッドです。
ストア名を指定して、存在すればjson型のレスポンスで返しています。
ストアが存在しない場合もメッセージをjson型のレスポンスで返しています。
@app.route('/stores/<>')でappにURIを登録しています。(デフォルトIPは'http://127.0.0.1:5000'に自動的に指定されます。)
このURIが叩かれたときに、下のメソッドが呼ばれます。引数にURI中の<>を代入しています。
jsonify( )は辞書型からjson型を作成するメソッドです。
# POST /store data: {name:}
def create_store():
request_data = request.get_json()
store = next(filter(lambda x: x["name"]==request_data["name"], stores), None)
if store != None:
return jsonify({"message": "store named {} already exist.".format(request_data["name"])})
else:
new_store = {
"name": request_data["name"],
"items": request_data["items"]
}
stores.append(new_store)
return jsonify({"message": "{} store is added.".format(request_data["name"])})
POSTメソッドです。
URI指定の際に、POSTを指定しています。(デフォルトはGETが指定されています。)
request.get_json()でリクエストボディを取得できます。
同じ名前のストアがなければ、リクエストボディのデータを持ったストアをデータベースに加えます。
PUTメソッドとDELETEメソッドについては、特に追加情報がないので割愛します。
# GET /stores
@app.route('/stores')
def get_stores():
return jsonify({'stores': stores})
CRUD操作の確認用にDB全体を取得するAPIをつくっておきました。
#ホーム画面にhtmlを読み込んでみる。
# GET /
@app.route('/')
def home():
return render_template("index.html")
htmlファイルを呼び出せます。
呼び出し先で、DB全体に対するGETメソッドを呼び出すように設定しています。
app.run(port=5000)
最後にアプリケーションを起動する記述をします。
ポート番号を指定しなくてもデフォルト5000がデフォルトなのですが、明言するためにあえて書いています。
もちろん他のポート番号も指定できます。
動作確認
実行
$ python sampleapp.py
* Serving Flask app "sampleapp" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
確認
Postman(HTTPリクエストが簡単に行えるツール)を使用して確認しました。
CRUDapiの動作が確認できました。
GET (stores)
POST
新しいストアをりクエストbodyに入れて登録します。
確認 (GET (stores))
ホーム画面
他のCRUDも同様に動作します。
感想
python/Flaskを使用すれば、
短時間に簡易なコードでwebAPIを作成していけそうです。
当初の目的には使用しないので...ボットwebApiとかとして弔ってあげたいと思います。