web-dev-qa-db-ja.com

PDISTICモデルのFASTAPIフォームデータ

私はHTMLフォームからデータを送信しようとしています。
[。]このコードを使って

from fastapi import FastAPI, Form
from pydantic import BaseModel
from starlette.responses import HTMLResponse


app = FastAPI()

@app.get("/form", response_class=HTMLResponse)
def form_get():
    return '''<form method="post"> 
    <input type="text" name="no" value="1"/> 
    <input type="text" name="nm" value="abcd"/> 
    <input type="submit"/> 
    </form>'''


class SimpleModel(BaseModel):
    no: int
    nm: str = ""

@app.post("/form", response_model=SimpleModel)
def form_post(form_data: SimpleModel = Form(...)):
    return form_data

HTTPステータス422未処理のエンティティでエラーを表示する

{"detail":[{"loc":["body"、 "form_data"、 "msg": "required"、 "type": "value_error.missing"}]}

同等のCURLコマンド(FIRFOXによって生成された)IS

curl ' http:// localhost:8001/form 'h' content-type:アプリケーション/ X-www-form-urlencoded '--data' no = 1 = 1 = abcd '

ここで要求本文にはno=1&nm=abcdが含まれています

私は何が悪いのですか?

6
shanmuga

私たちがPDISTICとしてFASTAPIフォームを使用するのに役立つソリューションを見つけました:)
[。]私のコード:

class AnyForm(BaseModel):
    any_param: str
    any_other_param: int = 1

    @classmethod
    def as_form(
        cls,
        any_param: str = Form(...),
        any_other_param: int = Form(1)
    ) -> AnyForm:
        return cls(any_param=any_param, any_other_param=any_other_param)

@router.post('')
async def any_view(form_data: AnyForm = Depends(AnyForm.as_form)):
        ...
 _

通常の形式としてSwaggerに表示されています
[。]私は、それはより一般的なものに書くことができます、多分私は答えを返して編集します。

[更新しました]

私はそれをデコレータとしてそれをより一般的に書いた

import inspect
from typing import Type

from fastapi import Form
from pydantic import BaseModel
from pydantic.fields import ModelField

def as_form(cls: Type[BaseModel]):
    new_parameters = []

    for field_name, model_field in cls.__fields__.items():
        model_field: ModelField  # type: ignore

        if not model_field.required:
            new_parameters.append(
                inspect.Parameter(
                    model_field.alias,
                    inspect.Parameter.POSITIONAL_ONLY,
                    default=Form(model_field.default),
                    annotation=model_field.outer_type_,
                )
            )
        else:
            new_parameters.append(
                inspect.Parameter(
                    model_field.alias,
                    inspect.Parameter.POSITIONAL_ONLY,
                    default=Form(...),
                    annotation=model_field.outer_type_,
                )
            )

    async def as_form_func(**data):
        return cls(**data)

    sig = inspect.signature(as_form_func)
    sig = sig.replace(parameters=new_parameters)
    as_form_func.__signature__ = sig  # type: ignore
    setattr(cls, 'as_form', as_form_func)
    return cls
 _

そして使用法はように見えます

class Test1(BaseModel):
    a: str
    b: int


@as_form
class Test(BaseModel):
    param: str
    test: List[Test1]
    test1: Test1
    b: int = 1
    a: str = '2342'


@router.post('/me', response_model=Test)
async def me(request: Request, form: Test = Depends(Test.as_form)):
    return form
 _
4
Nikita Davydov

以下のようなデータフォームを使用できます。

@app.post("/form", response_model=SimpleModel)
def form_post(no: int = Form(...),nm: str = Form(...)):
    return SimpleModel(no=no,nm=nm)
 _
2
Includeamin

フォームデータをクラスに抽象化することを見るだけでは、プレーンクラスでそれを実行できます。

from fastapi import Form, Depends

class AnyForm:
    def __init__(self, any_param: str = Form(...), any_other_param: int = Form(1)):
        self.any_param = any_param
        self.any_other_param = any_other_param

    def __str__(self):
        return "AnyForm " + str(self.__dict__)

@app.post('/me')
async def me(form: AnyForm = Depends()):
    print(form)
    return form
 _

そしてそれはまたパイインターモデルに変わることができます

from uuid import UUID, uuid4
from fastapi import Form, Depends
from pydantic import BaseModel

class AnyForm(BaseModel):
    id: UUID
    any_param: str
    any_other_param: int

    def __init__(self, any_param: str = Form(...), any_other_param: int = Form(1)):
        id = uuid4()
        super().__init__(id, any_param, any_other_param)

@app.post('/me')
async def me(form: AnyForm = Depends()):
    print(form)
    return form
 _
1
Kassym Dorsel

私はここに見つかった解決策を実装しました Mause Solution そしてそれはうまくいったようです

[。] [。] fasepi.testclient import testclient [。] for fastapi import fastapiから、Formipi、Forms。Pydantic Import Basemodel [。] [。] 
 [。] [。]。__署名__署名__署名__署名__署名__署名__署名__署名__署名__署名__署名__署名__署名__署名__署名__署名__._________________________________________________________________________________________________________________________________________________________________________________ = [[。] arp.REPLACE(DEFAULT = FORM(...))[。__署名__。 。____ [。] [。] [。] @ ____Body [。]クラスアイテム(Basemodel):[。]【】名前:STR [。] [。] [。] [。] [。] [。] [。] [。] [。] @ app.post( '/ test'、response_model = item)[。] defエンドポイント(項目:item = depenses(item)):[。) 。]アイテム[。] [。] [。] [。] [。] [。] [。] [。] [。] [。] [。] [。] [。] r = tc.post( '/ test') 、DATA = {'name': 'name'、 'wonther': '別の'})[。] [。] r.Status_Code == 200 [。== = '{' name ':' another '、' another ':' another '} [。] [。] [。] 。]
0
stefanlsd