2022-12-12

flask

python

Posted by

applemango

今回はflaskの基本構文を紹介していきます

あまり詳しくは紹介しないので詳しく知りたい人は各自調べてください(責任と存在意義の放棄)

今回はapiで使う前提なのでjinja(frontend)などを省いています

何もしないコード

from flask import Flask

app = Flask(__name__)

if __name__ == '__main__':
  app.run(debug=True, host='0.0.0.0', port=5000)

このコードは本当に何もしません

ルーティング

まずは127.0.0.1:5000/にアクセスするとHello, world!と表示するコードを追加しましょう

ルーティングには幾つかの方法がありますが一番簡単な方法が@app.routeを使う方法です

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/")
def index():
    return jsonify({"msg": "Hello, world!"})

if __name__ == '__main__':
  app.run(debug=True, host='0.0.0.0', port=5000)

もしかすると/user/abc/user/osakaなど動的に変更したい場合もあるでしょう、そのようなときは/user/<username>などのようにすれば解決できます

@app.route("/user/<username>")
def index(username):
    return jsonify({"msg": "hey {}".format(username)})

また型を付ける事も出来ます

@app.route("/user/<string:username>")
#文字列(デフォルト

@app.route("/user/<int:username>")
# 整数

@app.route("/user/<float:username>")
# 小数

@app.route("/user/<path:username>")
# "/"を使える以外は、文字列と同じ

@app.route("/user/<any:username>")
# 上記のどれか

@app.route("/user/<uuid:username>")
# uuid文字列

場合によってはデフォルトが必要になる事もあるでしょう、ぴったりの機能があります

@app.route('/users/', defaults={'page': 1})
@app.route('/users/page/<int:page>')

これで一通りできました、ですがまだ大事な事を忘れています

メソッド

@app.route("/")

このコードは暗黙的に以下のコードと同等です

@app.route("/", methods=["GET"])

その他にもPOST,DELETEがあります

@app.route("/", methods=["POST"])
@app.route("/", methods=["DELETE"])

複数の指定もできます

@app.route("/", methods=["GET", "POST"])

リクエスト

クライアントからリクエストされたデータを取得するにはrequestクラスを使います

from flask import request

主にこのクラスを使い、リクエストされたデータを参照します

色々ありますがまずは、よく使う物を紹介します

request.args
"""
URLのクエリ文字列をwerkzeug.ImmutableMultiDictクラスで取得する
ImmutableMultiDictクラスの取り扱い方に関しては後述します
"""

request.form
"""
postなどのformデータを取得します
こちらもImmutableMultiDictで取得します
"""

request.headers
"""
headerのデータを取得します
こちらも同じです
"""

request.files
"""
fileを取得します
同じ
"""

werkzeug.ImmutableMultiDictからデータを取り出す

ここではrequest.argsを例に解説しますがrequest.formなどでも同じように使えます

データを取り出すのに一番簡単方法は.getを使う事です

request.args.get(key, default=None, type=None)
"""
全て指定した場合
request.args.get("x", default=1, type=int)
"""

例えば127.0.0.1:3000/?x=10&y=50の場合request.argsで取得できるデータはImmutableMultiDict([('x', '10'), ('y', '30')])です

つまりxを取得したい場合request.args.get("x")となります

defaultは例えば127.0.0.1:3000/?y=50の場合Noneが返されますが,

デフォルトを指定した場合defaultの値が返されます

typeはデフォルトではargsの値に関係なく全てstr型で返されますが、型を指定した場合、指定した型で返されます、strから指定した型に変換した時にエラーが出た場合はdefaultの値が返されます

getのコード

ImmutableMultiDictについての詳細

画像やファイルを取り出して保存する

最小例

import os

basedir = os.path.abspath(os.path.dirname(__file__))
file_path = os.path.join(basedir, 'contents')

@app.route("/image", methods=["POST"])
def image_save():
    """
    今回は'file'と言う名前のfileを取り出していますが、適度変えてください
    """
    file = request.files.get("file")
    file.save(os.path.join(file_path, filename))  
    return jsonify({"path": filename}),200

上記の最小例でも機能しますが、少し不安です、画像のみを保存したい場合や安全に保存したい場合は少し手を加える必要があります

from werkzeug.utils import secure_filename
import os

basedir = os.path.abspath(os.path.dirname(__file__))
file_path = os.path.join(basedir, 'contents')

ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg'])
def allowed_file(filename):
	return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route("/image", methods=["POST"])
def image_save():
    file = request.files.get("file")
    if not file or not file.filename or not allowed_file(file.filename):
        return jsonify("file not allowed"), 400
    filename = secure_filename(file.filename)
    file.save(os.path.join(file_path, filename))        
    return jsonify({"path": filename}),200

レスポンス

jsonを返す

jsonを返す場合はjsonifyを使います

@app.route("/")
def index():
    return jsonify({"msg": "Hello, world!"})

画像やファイルを返す

画像やファイルなどを返す場合はsend_from_directoryを使います

import os
from flask import send_from_directory

basedir = os.path.abspath(os.path.dirname(__file__))
file_path = os.path.join(basedir, 'contents')

@app.route("/image/<string:path>", methods=["GET"])
def image_path(path):
    return send_from_directory(file_path, path)

status code

status codeを返したい場合は、2番目の戻り値で指定します

@app.route("/")
def index():
    from random import random
    if(random() < 0.5):
        return jsonify({"msg": "変態!!"}), 418
   return jsonify({"msg": "別にアンタのことなんか好きじゃないんだからね!"}), 200

主なstatus codeの一覧

設定

時に設定をいじることもあります設定を変更する方法は、色々ありますがここではfrom_mappingを使います

app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
    SECRET_KEY = "secret"
    ,JSON_AS_ASCII = False
)

from_mapping以外にfrom_fileなど色々あります

終わり

これで一通り終わりました、だぶん、きっと

このドキュメントどう?

emoji
emoji
emoji
emoji