2021年5月16日日曜日

Flask で controller をクラスで管理する (Pluggable Views)

Flask で controller をクラスで管理する (Pluggable Views)

概要

Flask で Controller (view) をクラスで管理してあとからルーティングルールに追加する方法を紹介します コントローラごとにクラスファイルを作成できるので管理が楽になることがあります

環境

  • macOS 11.3.1
  • Python 3.8.7

flask オブジェクトの作成とメインスクリプト

まずは flask オブジェクトの作成とそれを run するメインスクリプトを作成します flask app オブジェクトへの設定投入などは flask_app.py で行うようにします

  • vim main/__init__.py
from main.flask_app import FlaskApp

app = FlaskApp().create_flask_app()
  • vim main/flask_app.py
from flask import Flask

from views.html_view import HtmlView

class FlaskApp():
    def create_flask_app(self):
        app = Flask(__name__)
        return app

HTML を返却するコントローラをクラスで作成する

まずは単純な HTML を返却する View を作成します クラスとしてコントローラを作成する際のポイントは flask.views.View を継承したクラスを作成し dispatch_request を実装する必要がある点です

  • vim views/html_view.py
from flask.views import View

class HtmlView(View):

    def dispatch_request(self):
        return "<html><body>hello</body></html>"

この View を flask app に登録します 登録する際は add_url_rule を使います

  • vim main/flask_app.py
from flask import Flask

from views.html_view import HtmlView

class FlaskApp():
    def create_flask_app(self):
        app = Flask(__name__)
        app.add_url_rule('/html', view_func=HtmlView.as_view('html_view'))
        return app

これで OK です

動作確認

アプリを起動して確認してみます

  • FLASK_APP=main pipenv run flask run

curl で確認すると html が返ってくることが確認できます

  • curl -v localhost:5000/html

RESTful API のようなコントローラを作成する場合は

flask.views.View ではなく flask.views.MethodView を継承してクラスを作成します そうすることで dispatch_request ではなく get/post といった HTTP メソッド名で関数を定義することでそのメソッドごとのハンドラを定義することができます

  • vim views/json_view.py
from flask.views import MethodView
from flask import jsonify

class JsonView(MethodView):

    def get(self):
        return jsonify({"method":"get"})

    def post(self):
        return jsonify({"method":"post"})

これを add_url_rule で登録します メソッドは複数登録できますがパスと View は 1対1 の関係なので注意してください

  • vim main/flask_app.py
from flask import Flask

from views.html_view import HtmlView
from views.json_view import JsonView

class FlaskApp():
    def create_flask_app(self):
        app = Flask(__name__)
        app.add_url_rule('/html', view_func=HtmlView.as_view('html_view'))
        app.add_url_rule('/json', view_func=JsonView.as_view('json_view'))
        return app

動作確認

先程同様にアプリを起動して動作確認しましょう

  • FLASK_APP=main pipenv run flask run

curl で確認します

  • curl -XGET localhost:5000/json
  • curl -XPOST localhost:5000/json

View 生成時にコンストラクタを使って DI することもできる

単純に View に引数付きで __init__ を実装しましょう そして as_view で渡したい値を指定することで View のクラスのフィールドとして扱うことができます

  • vim views/json_view.py
from flask.views import MethodView
from flask import jsonify

class JsonView(MethodView):
    def __init__(self, method_name):
        self.method_name = method_name

    def get(self):
        return jsonify({"method":self.method_name})

    def post(self):
        return jsonify({"method":self.method_name})
  • vim main/flask_app.py
from flask import Flask

from views.html_view import HtmlView
from views.json_view import JsonView

class FlaskApp():
    def create_flask_app(self):
        app = Flask(__name__)
        app.add_url_rule('/html', view_func=HtmlView.as_view('html_view'))
        method_name = "HOGE"
        app.add_url_rule('/json', view_func=JsonView.as_view('json_view', method_name))
        return app

先ほどと同じように動作確認すれば値が変わっていることが確認できると思います

最後に

app.route を使う方法がメジャーだとは思いますが正直 View を使うほうが実用性はあると思います

flask の GettingStarted が app.route を使う方法なのでなかなかこの方法にたどり着かないのが悲しい感じです

参考サイト

0 件のコメント:

コメントを投稿