コンテンツにスキップ

返信する

fastapi response_modelでpydanticモデルの代わりにormarモデルを使用できます。

もちろん、必要に応じてormar. Modelsをpydanticと組み合わせて使用することもできます。

レスポンスで最も一般的なタスクの1つは、レスポンスデータに含めたくないフィールドを除外することです。

これはormarでさまざまな方法で行うことができるため、以下のオプションを確認して、状況に最適なものを選択できます。

応答からフィールドを除外します

オプションのフィールド

各オプションフィールドは必須ではないことに注意してください。つまり、応答とリクエストの両方でオプションフィールドをスキップできます。

(任意/多数/すべて)次の場合、フィールドは必要ありません。

  • フィールドはnullable=Trueとしてマークされます
  • フィールドにはデフォルト値または提供される機能があります。つまり、default="Test"です
  • フィールドにはserver_default値が設定されています。
  • Fieldはautoincrement=Trueprimary_keyフィールドです(ormarに注意してください。Integermain_keyはデフォルトでautoclimentです)

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
base_ormar_config=ormar. OrmarConfig(ベースの設定
    メタデータ
    データベース
)

class User(ormar. Model):
    base_or_config. copy()

    id: int=ormar.Integer(プライマリキー=True)
    email: str=ormar.String(max_length=255)
    パスワード: str=ormar.String(max_length=255)
    first_name: str=ormar.String(max_length=255,nullable=True)
    last_name: str=ormar.String(max_length=255)
    カテゴリ: str=ormar.String(max_length=255,default="User")

上記の例では、フィールドid(自動増分整数)、first_name(nullable=Trueを使用)、およびカテゴリ(デフォルト値を使用)はオプションであり、応答でスキップでき、モデルは引き続き検証します。

フィールドを空にできる場合は、作成時やレスポンスのペイロードに含める必要がないため、上記の例に基づいて次のことができます。

1
2
3
4
#アプリがFastApiアプリであることに注意してください
@app.post("/users/", response_model=User)#ここでは、応答にormar.Modelを使用します
async def create_user(user: User):#ここでは、リクエストパラメータにormar.Modelを使用します
    return awaituser.save()

つまり、リクエストでie first_nameを渡さなかった場合、正しく検証され(フィールドはオプションであるため)、データベースに保存され、このフィールドなしで保存されたレコードが返されます(これも検証されます)。

!!!Noteフィールド値を渡していなくても、フィールド自体はresponse_modelに存在することに注意してください。

1
結果からフィールドを完全に除外したい場合は、読み込んでください。

FastApi応答_モデル_除外

Fastapiには、一連の(またはリストの)フィールド名を受け取るresponse_model_cludeがあります。

これには制限があります。ormarとpydanticは辞書も受け入れているため、除外/包含列をネストされたモデルに設定することもできます(詳細は以下を参照)

警告response_modelを使用する場合、必須フィールドは検証中に失敗するため、除外できないことに注意してください。

1
2
3
@app.post("/users/", response_model=User,response_model_除外={"password"})
async def create_user(user: User):
    return awaituser.save()

上記のエンドポイントは次のように検索できます:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
starlette. testclientからTestClientをインポート

client=TestClient(アプリ)

クライアントをクライアントとして:
        #pkがないことに注意してください
        ユーザー={
            "email":"test@domain.com",
            "パスワード":"^*^%A*DA*IA AA",
            "first_name":"ジョン",
            "last_name":"Doe",
        }
        response=client.post("/users/", json=user)
        #除外されたフィールドが応答から完全に消えていることに注意してください
        assert"password"not in response. json()
        #レスポンスを読み、モデルを初期化する
        create_user=User(**response. json())
        #note pkは自動インクリメントで設定されます
        アサートcreated_user.pkはなし
        #初期化されたモデルでもパスワードが欠落していることに注意してください
        assert create_user. passwordはなし

!!!(注)上の例のパスワードフィールドが応答データから完全に消える方法に注意してください。

1
このメソッドは、必須でないフィールドにのみ使用できることに注意してください。

ネストされたモデルの除外

fastapiはフィールド名のセットのみを渡すことを許可しているため、単に除外しますが、response_model_排他を使用する場合は、ormarの方が賢明です。

ormarでは、2種類のシンボルを使用してネストされたモデルを除外できます。

1つ目は、モデルツリー構造を表すフィールドがネストされたディクショナリで、2つ目は、二重アンダースコアで区切られたフィールド名パスです。

ユーザーカテゴリが別のモデルであると仮定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
base_ormar_config=ormar. OrmarConfig(ベースの設定
    メタデータ
    データベース
)

class Category(ormar. Model):
    or_config=base_or_config. copy(tablename="カテゴリ")

    id: int=ormar.Integer(プライマリキー=True)
    name: str=ormar.String(max_length=255)
    優先度: int=ormar.Integer(nullable=True)


class User(ormar. Model):
    base_or_config. copy()

    id: int=ormar.Integer(プライマリキー=True)
    email: str=ormar.String(max_length=255)
    パスワード: str=ormar.String(max_length=255)
    first_name: str=ormar.String(max_length=255,nullable=True)
    last_name: str=ormar.String(max_length=255)
    カテゴリー:オプション[カテゴリー]=ormar. ForeignKey(カテゴリー、関連名="カテゴリー")

レスポンスのカテゴリから優先順位を除外する場合でも、fastapiパラメーターを使用できます。

1
2
3
@app.post("/users/", response_model=User,response_model_除外={"category__priority"})
async def create_user(user: User):
    return awaituser.save()

二重アンダースコアを使用してより深いモデルに入ることができ、ネストされたモデルから複数のフィールドを除外する場合は、それらの前にフルパスを追加する必要があることに注意してください。例では response_model_exclude={"category__priority", "category__other_field", category__nested_model__nested_model_field} ETC。

!!!注除外の可能性と、除外辞書または設定の構築方法の詳細については、ドキュメントのフィールドセクションを参照してください

注意fastapiはresponse_model_cludeパラメータの他にpydanticから継承した他のパラメータもサポートしていることに注意してください。これらはいずれもormarにも適用されますが、多少のニュアンスの違いがあるかもしれませんので、ドキュメントのdict部分を読んでおくとよいでしょう。

Model. model_dump()から除外する

または、ormar. Modelから辞書を返して使用することもできます。

このように、除外/インクルードを辞書として設定***ストされたモデル上のフィールドを除外することもできます。

!!!response_modelを使用しないことを警告すると、理論的には応答は任意の形式にすることができるため、APIドキュメントには応答の例とパターンがありません。

1
2
3
4
5
@app.post("/user 2/", response_model=User)
async def create_user 2(user: User):
    ユーザー=awaituser.save()
    return user. model_dump({'password'}を除外)
    #は、カテゴリの優先順位を除外するために、user. model_dump(除外={'カテゴリ':{'priority'}})を返すようなものでもあります。

!!!注上記の例では、リクエストでパスワードフィールドを渡してもパスワードフィールドは無効になりますが、応答スキーマの一部であり、値がNoneに設定されているため、このフィールドは存在します。

この方法でフィールドを完全に除外したい場合は、response_modelを使用せず、モデルのmodel_dump()で除外するだけです

または、ormarモデルからディクショナリを1つだけ返すこともできます。このように、除外/インクルードをディクショナリに設定して、ネストされたモデル上のフィールドを除外することもできます。

!!!注理論的には、ここでは応答の検証が失われますが、ormar. Modelsで操作しているため、データベースクエリの後に応答データが検証されます(ormarモデルはpydanticモデルであるため)。

そのため、response_modelを完全にスキップすると、次のようにできます。

1
2
3
4
@app.post("/user 4/")#note no response_model
async def create_user 4(user: User):
    ユーザー=awaituser.save()
    return user. model_dump({'last_name'}を除外)

!!!注response_modelをスキップすると、返された後にレスポンスが検証されなくなるため、必須フィールドを除外できるようになりました。

1
このソリューションのコストは、ファスタピの観点から不明な応答スキーマとしてのAPIドキュメントも緩んでいることです。

ormar. Modelからpydanticモデルを生成する

フィールドを除外するタスクは非常に一般的であるため、ormarには、すべてのフィールドを再入力することなく、既存のormar. Modelsからpydanticモデルを生成する特別な方法があります。

このメソッドは、すべてのモデルクラスで使用できるget_pydantic()メソッドです。

1
2
3
4
5
#Userにパスワードがなく、入れ子になったCategoryに優先順位がないモデルのツリーを生成する
ResponseUser=User. get_pydantic(除外={"パスワード":。。。、"カテゴリー":{"priority"}})
@app.post("/user 3/", response_model=ResponseUser)#ここで生成されたモデルを使用する
async def create_user 3(user: User):
    return awaituser.save()

!!!注さらに多くのサンプルを表示して詳細を読むには、ドキュメントのget_pydanticセクションにアクセスしてください。

警告get_pydanticメソッドは、モデル内のループを回避できるアルゴリズムに基づいて、ネストされたモデルツリー内のすべてのモデルを生成します(model_dump()、select_all()などで使用されるアルゴリズムと同じです)

1
2
3
つまり、入れ子になったモデルは親モデルへの参照を持たないことを意味します(デフォルトではormar関係は双方向です)。

また、与えられたモデルが木に複数回存在する場合、ピダンティックモデルでは2倍になります(各発生には別々のモデルがあります)。

そうすれば、ツリーの異なる葉に異なるフィールドを除外/含めることができます。

独立したカンチレバーモデル

最終的な解決策は、個別のpydanticモデルを手動で作成することです。通常のfastapiアプリケーションとまったく同じように動作するため、異なるレスポンスとリクエストモデルなどを使用できます。

サンプル:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
pydanticをインポート

class UserBase(pydantic. BaseModel):
    model_config=pydantic. ConfigDict(from_属性=True)

    メール: str
    ファーストネーム: str
    最後の名前: str


@app.post("/user 3/", response_model=UserBase)#ここではpydanticモデルを使用します
async def create_user 3(user: User):#ここではormarモデルを使用します(もちろん、ここでもpydanticを使用できます)
    return awaituser.save()