FastAPI python

FastAPIで関数ではないクラスオブジェクトをDependsで依存性注入する方法

スポンサーリンク

概要

最近FastAPIを触り始めたのですが、Dependsで関数ではなくクラスインスタンスを注入するための個人的なメモです。

スポンサーリンク

説明

Dependsとは

簡単に言ってしまうと、FastAPI専用のD/I(依存性注入)の仕組みです。

実際に各HTTPメソッドが呼び出される前に、Dependsに指定した関数を実行し、その戻り値を引数として渡すことができます。

よく挙げられる使用用途としては、下記になります。

  1. UnitTestでスタブやモックなどの処理に置き換えが可能
  2. 前処理の共通化 (ヘッダの特定のパラメータチェック、ユーザーの認証チェックなど)
  3. OpenAPIのドキュメントのスキーマなどに統合

2に関しては、他のWebフレームワークでもミドルウェア機能として提供されていて、リクエストの前後に処理を挟むために使われることが多いかと思います。 (ただしFastAPIにもミドルウェア機能はあり。)

より詳細な情報は公式ページの説明を参照してください。

 

個人的に感じた点

1つのコードで説明するような簡単なサンプルでは、先に挙げた関数を直接渡してしまえばいいですが、下記の点で少し不便(使いにくい)と感じました。

  • ルーティングの定義が書かれたコード内に、特定のロジックを持つ関数を書くのは何か気持ち悪い
  • 固定処理じゃ無い場合には、関数のスコープ外に設定などを持たせないといけない

そこで関数ではなく、クラス自体のインスタンスを渡せないのかと思いました。そうすることで、コンストラクタで設定を渡すことでクラス内に各種設定なども持たせることができます。

 

クラスによる依存性注入

公式の解説にも書いてありますが、クラスを使った依存性の注入も可能になっています。

 

ただ、これだと実際にはコンストラクタが呼ばれるだけなので、初期化処理で何か設定を持たせるとなると毎回処理が実行されてしまいます。

コンストラクタ自体はモジュール内の初期化処理などで、別途呼び出しを行い、設定などを保持させて、それらの設定を使って別途処理をしたいので目的に合いません。

もう少し探ってみたところ、セキュリティの項目で使用されている、OAuth2PasswordBearerがまさにやりたいことを実現しているので実際のコードを覗いてみたところ、下記のように実行していました。

 

ということで、__call__関数を定義して、呼ぶことができるようです。

個人的にはなじみの無い関数なのですが、クラスのインスタンスをメソッドとして呼び出した際に呼ばれる機能のようですね。

 

下記のように__call__関数を記載して、別のスコープで作成したクラスインスタンス自体をDependsに渡すと、この__call__がリクエストの度に実行されてやりたいことが実現できまました。

コンストラクタで固定の設定を持たせた上で、特定の処理を実行させたいということが実現できました。

 

-FastAPI, python

© 2024 nobu blog Powered by AFFINGER5