fastapi form data with pydantic model

前端 未结 3 606
滥情空心
滥情空心 2020-12-16 07:38

I am trying to submit data from html forms and on the validate it with pydantic model.
Using this code

from fastapi import FastAPI, Form
from pydantic im         


        
相关标签:
3条回答
  • 2020-12-16 08:13

    I found a solution which can help us to use FastAPI forms as pydantic as well :)
    My code:

    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)):
            ...
    

    It's showed in the swagger as usual form
    I think, it can be written more generic, maybe I will return and edit the answer.

    [UPDATED]

    I've written it more generic as a decorator

    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
    

    And usage looks like

    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
    
    0 讨论(0)
  • 2020-12-16 08:13

    you can use data-form like below:

    @app.post("/form", response_model=SimpleModel)
    def form_post(no: int = Form(...),nm: str = Form(...)):
        return SimpleModel(no=no,nm=nm)
    
    0 讨论(0)
  • 2020-12-16 08:21

    If you're only looking at abstracting the form data into a class you can do it with a plain class

    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
    

    And it can also be turned into a Pydantic Model

    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
    
    0 讨论(0)
提交回复
热议问题