FlaskによるWebサービスの実装 Part2
Webサービスインターフェイスの改善
Part1 ではWebサービスTODOのRESTful APIの基本的な実装ができました。
APIに改善の余地があるか考えてみましょう。
クライアントはGETメソッドで返されたタスクIDからURIを構築する必要があります。
このこと自体は簡単な作業ですクライアントに問題となることはないのでしょうが、将来的にAPIのバージョンが変わったときにURIの変更が難しくなってしまいます。
そこで、タスクIDを返す代わりに、タスクを制御するURIを返すようにしておき、クライアントはそのURIを利用するようにしましょう。
準備
アプリケーションのディレクトリを作成します。
code: bash
$ mkdir -p $HOME/flask/todo_apiv2
$ cd $HOME/flask/todo_apiv2
Part1 からの app.py と tasks.pyをコピーします。
code: bash
$ cp $HOME/flask/todo_api/app.py .
$ cp $HOME/flask/todo_api/tasks.py .
次のように修正しましょう。
URIに含まれているAPIバージョンを変更
関数make_public_task() を追加
関数を修正:get_task()、get_tasklist()、create_task()、update_task()
code: app.py
from flask import (
Flask, jsonify, abort, make_response, request, url_for
)
from tasks import tasks
app = Flask(__name__)
def make_public_task(task):
new_task = {}
for field in task:
if field == 'id':
new_task'uri' = url_for('get_task', task_id=task'id', _external=True) else:
return new_task
@app.errorhandler(400)
def bad_request(error):
return make_response(jsonify({'error': 'Bad request'}), 400)
@app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
@app.route('/todo/api/v2.0/tasks/<int:task_id>', methods='GET') def get_task(task_id):
task = [task for task in tasks if task'id' == task_id] if len(task) == 0:
abort(404)
return jsonify({'task': make_public_task(task0)}) @app.route('/todo/api/v2.0/tasks', methods='GET') def get_tasklist():
@app.route('/todo/api/v2.0/tasks', methods='POST') def create_task():
if not request.json or not 'title' in request.json:
abort(400)
task = {
'description': request.json.get('description', ""),
'done': False
}
tasks.append(task)
return jsonify({'task': make_public_task(task)}), 201
@app.route('/todo/api/v2.0/tasks/<int:task_id>', methods='PUT') def update_task(task_id):
task = [task for task in tasks if task'id' == task_id] if len(task) == 0:
abort(404)
if not request.json:
abort(400)
if ('title' in request.json and
isinstance(type(request.json'title'), unicode)): abort(400)
if ('description' in request.json and
abort(400)
if ('done' in request.json and
type(request.json'done') is not bool): abort(400)
return jsonify({'task': make_public_task(task0)}) @app.route('/todo/api/v2.0/tasks/<int:task_id>', methods='DELETE') def delete_task(task_id):
task = [task for task in tasks if task'id' == task_id] if len(task) == 0:
abort(404)
return jsonify({'result': True})
if __name__ == '__main__':
app.run(debug=True, port=8080)
code: bash
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 358
Server: Werkzeug/1.0.1 Python/3.6.10
Date: Wed, 13 May 2020 16:39:49 GMT
{
"tasks": [
{
"description": "IPA 6 bottles",
"done": false,
"title": "Buy Beer",
},
{
"description": "Beef, Tofu, Sting Onion",
"done": false,
"title": "Buy groceries",
}
]
}
クライアントは返される uri の値を利用してリソースにアクセスすることができます。