美文网首页fastapi学习文档fastapi
fastapi教程翻译(十三): Response Model(

fastapi教程翻译(十三): Response Model(

作者: warmsirius | 来源:发表于2019-10-15 18:33 被阅读0次

    您可以在任何路径操作中使用参数 response_model 声明用于响应的模型:

    • @app.get()
    • @app.post()
    • @app.put()
    • @app.delete()
    • etc.

    一、response_model

    1. 举例

    from typing import List
    
    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
        tags: List[str] = []
    
    @app.post("/items/", response_model=Item) async def create_item(item: Item):
        return item
    

    注意

    • response_model是“ decorator”方法(getpost等)的参数。 不像所有参数和主体一样,具有路径操作功能。
    • 它接收的类型与您为Pydantic模型属性声明的类型相同,因此它可以是Pydantic模型,但也可以是例如 一个Pydantic模型的清单,例如List [Item]

    2. response_model功能

    FastAPI 将使用 response_model 实现以下功能:

    • 将输出数据转换为其类型声明。
    • 验证数据。
    • 在OpenAPI路径操作中为响应添加一个JSON模式。
    • 将由自动文档系统使用。

    最重要的功能

    将输出数据限制为模型的数据.

    技术细节
    响应模型在此参数中声明,而不是作为函数返回类型注释声明

    因为路径函数实际上可能不会返回该响应模型,而是返回dict,数据库对象或其他模型,然后使用response_model,执行字段限制和序列化。

    二、返回相同的输入数据

    这里我们定义了一个UserIn模型,它会包含一个纯文本的密码:

    from fastapi import FastAPI
    from pydantic import BaseModel
    from pydantic.types import EmailStr
    
    app = FastAPI()
    
    class UserIn(BaseModel):
        username: str
     password: str    email: EmailStr
        full_name: str = None
    
    # Don't do this in production!
    # 不要在生产环境中使用这个!
    @app.post("/user/", response_model=UserIn)
    async def create_user(*, user: UserIn):
        return user
    

    我们正在使用此模型声明输入,并使用同一模型声明输出:

    from fastapi import FastAPI
    from pydantic import BaseModel
    from pydantic.types import EmailStr
    
    app = FastAPI()
    
    class UserIn(BaseModel):
        username: str
        password: str
        email: EmailStr
        full_name: str = None
    
    # Don't do this in production!
    @app.post("/user/", response_model=UserIn) async def create_user(*, user: UserIn):
        return user
    

    现在,每当浏览器使用密码创建用户时,API都会在响应中返回相同的密码。

    在这种情况下,这可能不是问题,因为用户自己正在发送密码。

    但是,如果我们对另一个路径操作使用相同的模型,则可能会将用户的密码发送给每个客户端。

    危险

    切勿在响应中发送用户的普通密码。

    三、添加一个输出模型

    我们可以改用纯文本密码创建输入模型,而没有明文密码则创建输出模型:

    from pydantic import BaseModel
    from pydantic.types import EmailStr
    
    
    class UserIn(BaseModel):
        username: str
        password: str
        email: EmailStr
        full_name: str = None
    

    在这里,即使我们的路径操作函数正在返回包含密码的相同输入用户:

    from fastapi import FastAPI
    from pydantic import BaseModel
    from pydantic.types import EmailStr
    
    app = FastAPI()
    
    class UserIn(BaseModel):
        username: str
        password: str
        email: EmailStr
        full_name: str = None
    
    class UserOut(BaseModel):
        username: str
        email: EmailStr
        full_name: str = None
    
    @app.post("/user/", response_model=UserOut)
    async def create_user(*, user: UserIn):
     return user 
    

    ...我们将response_model声明为我们的模型'UserOut',其中不包含密码:

    from fastapi import FastAPI
    from pydantic import BaseModel
    from pydantic.types import EmailStr
    
    app = FastAPI()
    
    class UserIn(BaseModel):
        username: str
        password: str
        email: EmailStr
        full_name: str = None
    
    class UserOut(BaseModel):
        username: str
        email: EmailStr
        full_name: str = None
    
    @app.post("/user/", response_model=UserOut) async def create_user(*, user: UserIn):
        return user
    

    因此,FastAPI 将负责过滤掉未在输出模型中声明的所有数据(使用Pydantic)。

    四、查看文档

    当您看到自动文档时,可以检查输入模型和输出模型是否都具有自己的JSON模式:

    两种模型都将用于交互式API文档:

    五、设置响应模型中的参数

    1. 响应模型中设置默认值

    比如:

    from typing import List
    
    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = 10.5
        tags: List[str] = [] 
    
    items = {
        "foo": {"name": "Foo", "price": 50.2},
        "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
        "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
    }
    
    @app.get("/items/{item_id}", response_model=Item, response_model_skip_defaults=True)
    async def read_item(item_id: str):
        return items[item_id]
    
    • description: str = None 有默认值 None.
    • tax: float = 10.5 有默认值 10.5.
    • tags: List[str] = [] 有默认值: [].

    但是,如果实际上没有存储它们,则可能要从结果中忽略它们。

    例如,如果您的模型在NoSQL数据库中具有很多可选属性,但是您不想发送很长的JSON响应(包含默认值)。

    2. 使用 response_model_skip_defaults 参数

    您可以设置 path操作装饰器 参数 response_model_skip_defaults = True

    from typing import List
    
    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = 10.5
        tags: List[str] = []
    
    items = {
        "foo": {"name": "Foo", "price": 50.2},
        "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
        "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
    }
    
    @app.get("/items/{item_id}", response_model=Item, response_model_skip_defaults=True) 
    async def read_item(item_id: str):
        return items[item_id]
    

    这些默认值将不会包含在响应中。

    因此,如果您向ID为foo的项目发送请求到该路径操作,则响应(不包括默认值)将为:

    {
        "name": "Foo",
        "price": 50.2
    }
    

    说明
    FastAPI使用具有其skip_defaults参数的Pydantic模型的.dict()来实现此目的。

    a. 具有默认值的字段的值的数据

    但是如果您的数据具有默认值的模型字段值,例如ID为bar的项目:

    {
        "name": "Bar",
        "description": "The bartenders",
        "price": 62,
        "tax": 20.2 }
    

    它们将包含在响应中。

    b. 数据具有与默认值相同的值

    如果数据具有与默认值相同的值,例如ID为baz的项:

    {
        "name": "Baz",
        "description": None,
        "price": 50.2,
        "tax": 10.5,
        "tags": [] 
    }
    

    FastAPI足够聪明(实际上,Pydantic足够聪明)可以认识到,即使descriptiontaxtags与默认值具有相同的值,它们也是显式设置的(而不是取自默认值) 。

    因此,它们将包含在JSON响应中。

    注意

    默认值可以是任何值,不仅可以是None。
    例如可以是一个 list ([]), 一个 float 值为10.5, 等等.

    3. response_model_includeresponse_model_exclude

    您还可以使用path操作装饰器 参数response_model_includeresponse_model_exclude

    他们使用带有属性名称的strstr包括(省略其余部分)或排除(包括其余部分)。

    如果您只有一个Pydantic模型,并且想要从输出中删除一些数据,则可以将其用作快速捷径。

    注意

    但是仍然建议使用上述想法,使用多个类而不是这些参数。

    这是因为即使您使用response_model_includeresponse_model_exclude来省略某些属性,在应用程序的OpenAPI(和文档)中生成的JSON模式仍将是完整模型的JSON模式

    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = 10.5
    
    items = {
        "foo": {"name": "Foo", "price": 50.2},
        "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
        "baz": {
            "name": "Baz",
            "description": "There goes my baz",
            "price": 50.2,
            "tax": 10.5,
        },
    }
    
    @app.get("/items/{item_id}/name", response_model=Item, response_model_include={"name", "description"}, )
    async def read_item_name(item_id: str):
        return items[item_id]
    
    @app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"tax"})
     async def read_item_public_data(item_id: str):
        return items[item_id]
    

    注意:

    语法{“ name”,“ description”}`用这两个值创建一个set。

    相当于 set(["name", "description"]).

    4. 使用 list代替set

    如果您忘记使用set而是使用listtuple,则FastAPI仍会将其转换为set,并且可以正常工作:

    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = 10.5
    
    items = {
        "foo": {"name": "Foo", "price": 50.2},
        "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
        "baz": {
            "name": "Baz",
            "description": "There goes my baz",
            "price": 50.2,
            "tax": 10.5,
        },
    }
    
    @app.get(
        "/items/{item_id}/name",
        response_model=Item,
     response_model_include=["name", "description"], )
    async def read_item_name(item_id: str):
        return items[item_id]
    
    @app.get("/items/{item_id}/public", response_model=Item, response_model_exclude=["tax"]) async def read_item_public_data(item_id: str):
        return items[item_id]
    

    六、概括

    使用路径操作修饰符的参数response_model定义响应模型,尤其是确保私有数据被过滤掉。
    使用response_model_skip_defaults仅返回显式设置的值。

    相关文章

      网友评论

        本文标题:fastapi教程翻译(十三): Response Model(

        本文链接:https://www.haomeiwen.com/subject/swosmctx.html