2020年12月18日金曜日

flask.g を使う場合は同一アプリコンテキスト内でないと参照できないので注意

概要

前回 flask.g の使い方を紹介しました
前回のサンプルは暗黙的に同一アプリコンテキスト配下で g を使っていました
flask は複数のアプリを 1 つのコードで書ける仕組みになっているためコンテキストを意識しないとコンテキスト配下にある g をうまく参照できないので注意が必要です

環境

  • macOS 11.1
  • Python 3.8.5
    • flask 1.1.2

アプリコード

例えば @app.route 外で profile.set して profile.get@app.route 内で参照するとします
この場合 set と get は同じアプリコンテキストから g を参照しないと同一の値が取得できません

  • vim app.py
from lib.profile import Profile

from flask import Flask
from flask import g

app = Flask(__name__)

profile = Profile(app)
profile.set()

@app.route("/")
def index():
    name, age, time = profile.get()
    return "{} - {} - {}".format(name, age, time)

@app.route("/update")
def update():
    profile.update_time()
    return "updated"

flask.g を管理するクラス

クラスにしてアプリケーションコンテキストを属性として管理します
こうすることで同一のアプリケーションコンテキストを参照することができます

  • vim lib/profile.py
import datetime
from flask import g


class Profile:
    def __init__(self, app):
        self.app = app
        self.ctx = app.app_context()

    def set(self, name='hawksnowlog', age=10, time=None):
        with self.ctx:
            if 'name' not in g:
                g.name = name 
            if 'age' not in g:
                g.age = age
            if 'time' not in g:
                g.time = datetime.datetime.now().isoformat()

    def get(self):
        with self.ctx:
            return g.name, g.age, g.time

    def update_time(self):
        with self.ctx:
            g.time = datetime.datetime.now().isoformat()

動作確認

  • FLASK_APP=app.py pipenv run flask run
  • curl localhost:5000/
  • curl localhost:5000/update

0 件のコメント:

コメントを投稿