リクエスト
fastapiリクエストの本体パラメータでpydanticモデルの代わりにormarモデルを使用できます。
もちろん、必要に応じてormar. Modelsをpydanticと組み合わせて使用することもできます。
リクエストで最も一般的なタスクの1つは、APIに送信されるロードに含めたくない特定のフィールドを除外することです。
これは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を使用)、およびカテゴリ(デフォルト値を使用)はオプションであり、応答でスキップでき、モデルは引き続き検証します。
フィールドを空にできる場合は、作成時やレスポンスのペイロードに含める必要がないため、上記の例に基づいて次のことができます。
!!!警告オプションのフィールドを渡す必要はありませんが、それでも渡すことができることに注意してください。誰かが値を渡すと、それを防ぐための措置を講じない限り、後で使用されます。
| #アプリがFastApiアプリであることに注意してください
@app.post("/users/", response_model=User)#ここでは、応答にormar.Modelを使用します
async def create_user(user: User):#ここでは、リクエストパラメータにormar.Modelを使用します
return awaituser.save()
|
これは、リクエストでie first_nameを渡さなかった場合、正しく検証され(フィールドがオプションであるため)、Noneがデータベースに保存されることを意味します。
ormar. Modelからpydanticモデルを生成する
フィールドを除外するタスクは非常に一般的であるため、ormarには、すべてのフィールドを再入力することなく、既存のormar. Modelsからpydanticモデルを生成する特別な方法があります。
このメソッドは、すべてのモデルクラスで使用できるget_pydantic()メソッドです。
| #Userにパスワードがなく、入れ子になったCategoryに優先順位がないモデルのツリーを生成する
RequestUser=User. get_pydantic(除外={"パスワード":。。。、"カテゴリー":{"priority"}})
@app.post("/user 3/", response_model=User)#ここでは、ormar/pydanticの両方を使用することもできます
async def create_user 3(user: RequestUser):#ここで生成されたモデルを使用する
ユーザーがpydanticであり、ormar Modelではないため、変換する必要があることに注意してください。
return await User(**user. model_dump()).save()
|
!!!注さらに多くのサンプルを表示して詳細を読むには、ドキュメントのget_pydanticセクションにアクセスしてください。
警告get_pydanticメソッドは、モデル内のループを回避できるアルゴリズムに基づいて、ネストされたモデルツリー内のすべてのモデルを生成します(model_dump()、select_all()などで使用されるアルゴリズムと同じです)
| つまり、入れ子になったモデルは親モデルへの参照を持たないことを意味します(デフォルトではormar関係は双方向です)。
また、与えられたモデルが木に複数回存在する場合、ピダンティックモデルでは2倍になります(各発生には別々のモデルがあります)。
|
そうすれば、ツリーの異なる葉に異なるフィールドを除外/含めることができます。
Mypyと型チェック
関数をpython型に代入すると(チェックされていないので)実行時にパスしてしまい、mypyのような静的型チェッカーが文句を言うので注意してください。
関数呼び出しの結果は特定のモデルで常に同じですが、動的に作成された型は許可されていません。
したがって、2つの選択肢があります。
1つ目は、タイプチェックをスキップするために#type: noneを追加するだけです
| RequestUser=User. get_pydantic(除外={"パスワード":。。。、"カテゴリー":{"priority"}})
@app.post("/user 3/", response_model=User)
async def create_user 3(user: RequestUser):#タイプ:無視
#note how now user is not ormar Modelだから変換する必要がある
return await User(**user. model_dump()).save()
|
2つ目はもう少しhackyで、fastapiを使用して関数パラメータを抽出する方法です。
指定された引数の__アノテーション__エントリを上書きできます。
| RequestUser=User. get_pydantic(除外={"パスワード":。。。、"カテゴリー":{"priority"}})
#アプリデコレータを使用しない
async def create_user 3(user: User):#ここでormarモデルを使用する
return await User(**user. model_dump()).save()
#生成されたモデルでユーザーパラメータの関数注釈エントリを上書きする
create_user 3.__annotations__["user"]=RequestUser
#アプリ関数(app. get、app.postなど)を手動で呼び出し、関数参照を渡す
app.post("/カテゴリ/", response_model=User)(create_user 3)
|
これにより、mypyはユーザーがormarモデルであると「考える」ことになりますが、リクエストでは重要ではないため(とにかくjsonized dictを渡し、保存する前に変換する必要があります)。
生成されたモデルはフィールドのサブセットになるため、必要なすべてのフィールドが検証され、未使用のフィールドはすべて実行時に失敗するため、これは引き続き機能するはずです。
独立したカンチレバーモデル
最終的な解決策は、個別のpydanticモデルを手動で作成することです。通常のfastapiアプリケーションとまったく同じように動作するため、異なるレスポンスとリクエストモデルなどを使用できます。
サンプル:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | pydanticをインポート
class User Create(pydantic. BaseModel):
model_config=pydantic. ConfigDict(from_属性=True)
メール: str
ファーストネーム: str
最後の名前: str
パスワード: str
@app.post("/user 3/", response_model=User)#ここではormarモデルを使用します(もちろん、ここでもpydanticを使用できます)
async def create_user 3(user: User Create):#ここでpydanticモデルを使用する
#request paramがpydanticモデルであり、ormarモデルではないことに注意してください。
#データベースを使用する前に、それを解析/ormarに変換する必要があります。
return await User(**user. model_dump()).save()
|