これは、なにをしたくて書いたもの?
以前に、Flask RESTfulを使ってみたのですが、JSONをやり取りするのに素のFlaskでもそんなに困らないのでは?と思いまして。
Flask-RESTful — Flask-RESTful 0.3.8 documentation
って、前のエントリの最後にも、そんなことを書いていましたね。前のエントリで書いた内容を、Flaskのみでちょっと
試してみましょうか。
環境
今回の環境は、こちらです。
$ python3 -V Python 3.8.2
Flaskをインストール。
$ pip3 install Flask
バージョン。
$ pip3 freeze click==7.1.2 Flask==1.1.2 itsdangerous==1.1.0 Jinja2==2.11.2 MarkupSafe==1.1.1 Werkzeug==1.0.1
まずは雛形を
まずはコードの雛形を作りましょう。
こんな感じで用意しました。
index.py
from datetime import datetime from flask import Flask, jsonify, request app = Flask(__name__) #### ここに、いろいろ書く if __name__ == '__main__': app.run(debug = True)
以降は、この部分にいろいろ追記していきたいと思います。
#### ここに、いろいろ書く
とりあえず、JSONを返してみよう
jsonifyを使えばよいみたいです。
こんな感じで。
@app.route('/') def hello_world(): return jsonify(message = 'Hello Flask!', now = datetime.now())
jsonifyを使うと、Content-Type
がapplication/json
となってくれるところがポイントです。
$ curl -i localhost:5000 HTTP/1.0 200 OK Content-Type: application/json Content-Length: 65 Server: Werkzeug/1.0.1 Python/3.8.2 Date: Thu, 17 Sep 2020 13:37:23 GMT {"message":"Hello Flask!","now":"Thu, 17 Sep 2020 22:37:23 GMT"}
URLパスに変数を入れる
Applicationオブジェクトのroute
に、ふつうに書けるようです。
こんな感じで。
@app.route('/var/<string:id>') def with_variable(id): return jsonify(request_id = id)
変数は、メソッドの引数として渡されます。
確認。
$ curl -i localhost:5000/var/12345 HTTP/1.0 200 OK Content-Type: application/json Content-Length: 28 Server: Werkzeug/1.0.1 Python/3.8.2 Date: Thu, 17 Sep 2020 13:51:08 GMT { "request_id": "12345" }
QueryStringやJSONを受け取る
QueryStringは、Request
から取得することができます。
QueryStringそのものを取得する場合は、query_string
を使います。bytestringで返ってくるので、今回は文字列にするように
decode
しています。
パラメーターとして取得したい場合は、args
を使います。
こんな感じで。
@app.route('/get') def with_query_string(): return jsonify( query_string = request.query_string.decode('utf-8'), request_param = request.args.get('param') )
確認。
$ curl -i localhost:5000/get?param=value HTTP/1.0 200 OK Content-Type: application/json Content-Length: 65 Server: Werkzeug/1.0.1 Python/3.8.2 Date: Thu, 17 Sep 2020 13:56:38 GMT { "query_string": "param=value", "request_param": "value" }
最後に、JSONを受け取ってみましょう。HTTPメソッドも、POSTに限定してみます。
JSONリクエストを取得するには、get_json
を使うのがよさそうです。
force = True
にしておくと、Content-Type
に関係なくJSONとして扱ってくれます。デフォルトでは、application/json
としなければ
JSONとして認識してくれません。
@app.route('/post', methods = ['POST']) def with_json(): json = request.get_json(force = True) return jsonify(request_json = json, request_name = json['name'])
確認。
$ curl -i localhost:5000/post -d '{"name": "value"}' HTTP/1.0 200 OK Content-Type: application/json Content-Length: 76 Server: Werkzeug/1.0.1 Python/3.8.2 Date: Thu, 17 Sep 2020 14:29:16 GMT { "request_json": { "name": "value" }, "request_name": "value" }
ざっと、前に書いた内容は確認できました。とりあえず、基本的なことはできるのではないでしょうか?
WSGIサーバーで動かしてみる
最後に、WSGIサーバー…今回もGunicornで動かしてみます。
$ pip3 install gunicorn
バージョン。
$ pip3 freeze | grep gunicorn gunicorn==20.0.4
起動。
$ gunicorn index:app [2020-09-17 23:30:43 +0900] [12500] [INFO] Starting gunicorn 20.0.4 [2020-09-17 23:30:43 +0900] [12500] [INFO] Listening at: http://127.0.0.1:8000 (12500) [2020-09-17 23:30:43 +0900] [12500] [INFO] Using worker: sync [2020-09-17 23:30:43 +0900] [12502] [INFO] Booting worker with pid: 12502
確認。
$ curl -i localhost:8000/get?param=value HTTP/1.1 200 OK Server: gunicorn/20.0.4 Date: Thu, 17 Sep 2020 14:30:53 GMT Connection: close Content-Type: application/json Content-Length: 55 {"query_string":"param=value","request_param":"value"}
こんな感じで、と。