クラス内でFastAPIを使用してルートを作成する方法 質問する

クラス内でFastAPIを使用してルートを作成する方法 質問する

クラス内にいくつかのルートが必要ですが、ルートメソッドにはattrが必要ですself(クラスの属性にアクセスするため)。ただし、FastAPIはself独自の必須引数を想定し、それをクエリパラメータとして配置します。

私が持っているのはこれです:

app = FastAPI()
class Foo:
    def __init__(y: int):
        self.x = y

    @app.get("/somewhere")
    def bar(self): return self.x

ただし、422に移動しない限り、は を返します/somewhere?self=something。これの問題は、 がselfstr になり、役に立たなくなることです。

self必須の引数として指定せずにアクセスできる方法が必要です。

ベストアンサー1

APIRouterこれは のメソッドを使用して実行できますadd_api_route

from fastapi import FastAPI, APIRouter


class Hello:

    def __init__(self, name: str):
        self.name = name
        self.router = APIRouter()
        self.router.add_api_route("/hello", self.hello, methods=["GET"])

    def hello(self):
        return {"Hello": self.name}


app = FastAPI()
hello = Hello("World")
app.include_router(hello.router)

例:

$ curl 127.0.0.1:5000/hello
{"Hello":"World"}

add_api_routeの2番目の引数(endpoint)は 型なのでCallable[..., Any]、どの呼び出し可能オブジェクトでも動作するはずです(FastAPIがその引数のHTTPリクエストデータを解析する方法を見つけられる限り)。この呼び出し可能オブジェクトは、FastAPIドキュメントではパス操作関数(以下、「POF」といいます)。

装飾方法がうまくいかない理由

警告: OPの回答のコードがなぜ機能しないのかの技術的な説明に興味がない場合は、この回答の残りの部分を無視してください。

@app.getクラス本体でメソッドを や の仲間で装飾しても、実際にはHello.helloではなくhello.hello(別名self.hello)を に渡すことになるため、機能しadd_api_routeません。バインドされたメソッドとバインドされていないメソッド(別名単に「関数」)Python 3以降) には異なる署名があります。

import inspect
inspect.signature(Hello.hello)  # <Signature (self)>
inspect.signature(hello.hello)  # <Signature ()>

FastAPI は、HTTP リクエスト (本文またはクエリ パラメータ) 内のデータを POF で実際に使用されるオブジェクトに自動的に解析しようとするために、さまざまな魔法を実行します。

バインドされていないメソッド (=通常の関数) ( Hello.hello) を POF として使用すると、FastAPI は次のいずれかを行う必要があります。

  1. ルートを含むクラスの性質について想定し、オンザフライで を生成self(つまり を呼び出すHello.__init__) します。これにより、FastAPI の複雑さが大幅に増す可能性があり、FastAPI 開発者は (当然のことながら) サポートすることに興味がないと思われるユースケースです。アプリケーション/リソースの状態を処理するための推奨される方法は、 を使用した外部依存関係に問題全体を委ねることのようですDepends

  2. 何らかの方法で、呼び出し元から送信された HTTP リクエスト データ (通常は JSON) からオブジェクトを生成できるようにしますself。これは、文字列やその他の組み込みデータ以外では技術的に実現不可能であるため、実際には使用できません。

OP のコードで何が起きるかは #2 です。FastAPI は、HTTP リクエスト クエリ パラメータからHello.hello(= self、型) の最初の引数を解析しようとしますが、明らかに失敗し、 を発生させます。これは、呼び出し元に HTTP 422 応答として表示されます。HelloRequestValidationError

selfクエリパラメータからの解析

上記の 2 を証明するために、FastAPI が実際にselfHTTP リクエストから「解析」できる場合の (役に立たない) 例を次に示します。

免責事項:以下のコードを実際のアプリケーションに使用しないでください。

from fastapi import FastAPI

app = FastAPI()

class Hello(str):
    @app.get("/hello")
    def hello(self):
        return {"Hello": self}

例:

$ curl '127.0.0.1:5000/hello?self=World'
{"Hello":"World"}

おすすめ記事