fastapi(十)-响应模式

本文深入探讨了FastAPI框架中响应模型的使用方法,包括如何设置response_model参数以转换、验证输出数据,以及如何在自动文档中适配响应JSON schema。同时,文章还介绍了如何通过response_model_include和response_model_exclude来快速指定返回属性,以及如何处理输入模型和输出模型之间的差异。

你可以在一下方法中设置相应的response_model参数:

  • @app.get()
  • @app.post()
  • @app.put()
  • @app.delete()
    eg:
 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是方法装饰器的参数不是函数的参数。

fastapi使用response_model的作用:
1、转换输出数据为声明的类型
2、验证数据
3、在openapi路径操作中添加响应json schema
4、在自动文档中适配
将输入模型和输入模型单独配置

from fastapi import FastAPI
from pydantic import BaseModel, 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

虽然user模型包括password字段,但是fastapi将根据输出模型适配相应的字段,

响应模型编码参数

在输出模型中属性可以设置默认值,但是当你不想让响应中出现这些默认值,可以使用:
response_model_exclude_unset=True
但是当将这些有默认值的属性设置新值后,他们将在response中返回,即使新值等于默认值。
response_model_include和response_model_exclude
如果你想快速的写出返回属性以及排除的返回属性,可以使用他们。
他们接收的值为str类型的set。

@app.get(
    "/items/{item_id}/name",
    response_model=Item,
    response_model_include={"name", "description"},
)

@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"tax"})

如果你使用list或者tuple来表示,fastapi将自动转换为set。

目前为止已经介绍了输入模型以及输出模型,但是还有其他的模型。
假如:
1、输入模型中包括password字段
2、输出模型中没有password字段
3、数据模型中将需要对password字段进行hash算法。
eg:

from fastapi import FastAPI
from pydantic import BaseModel, 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


class UserInDB(BaseModel):
    username: str
    hashed_password: str
    email: EmailStr
    full_name: str = None


def fake_password_hasher(raw_password: str):
    return "supersecret" + raw_password


def fake_save_user(user_in: UserIn):
    hashed_password = fake_password_hasher(user_in.password)
    user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
    print("User saved! ..not really")
    return user_in_db


@app.post("/user/", response_model=UserOut)
async def create_user(*, user_in: UserIn):
    user_saved = fake_save_user(user_in)
    return user_saved

关于user_in.dict()**
user_in 是pydantic模型的实例,pydantic模型有dict方法将会把模型的数据已dict的形式返回。

如果我们将字典类型作为函数的参数进行传值,那么就需要**符号来对其进行解包。以key-value的形式传入函数中。

UserInDB(**user_in.dict(), hashed_password=hashed_password)
以解包dict的形式进行传值,以及添加额外的key-value。

减少重复
减少代码的重复是fastapi的核心思想。
当代码的重复度增加,同事出现bug的机会以及安全问题和代码的重构的风险也会增加。
以上代码就存在着很多的重复。

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


class UserBase(BaseModel):
    username: str
    email: EmailStr
    full_name: str = None


class UserIn(UserBase):
    password: str


class UserOut(UserBase):
    pass


class UserInDB(UserBase):
    hashed_password: str


def fake_password_hasher(raw_password: str):
    return "supersecret" + raw_password


def fake_save_user(user_in: UserIn):
    hashed_password = fake_password_hasher(user_in.password)
    user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
    print("User saved! ..not really")
    return user_in_db


@app.post("/user/", response_model=UserOut)
async def create_user(*, user_in: UserIn):
    user_saved = fake_save_user(user_in)
    return user_saved

union或anyof
你可以声明响应为两个类型的union。那就意味着响应可能是这两个类型的任意一个。
可以使用python的typing.union来达到此目的。
eg:

from typing import Union

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class BaseItem(BaseModel):
    description: str
    type: str


class CarItem(BaseItem):
    type = "car"


class PlaneItem(BaseItem):
    type = "plane"
    size: int


items = {
    "item1": {"description": "All my friends drive a low rider", "type": "car"},
    "item2": {
        "description": "Music is my aeroplane, it's my aeroplane",
        "type": "plane",
        "size": 5,
    },
}


@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem])
async def read_item(item_id: str):
    return items[item_id]

同样的你也可以使用List或dict来定义响应。
@app.get("/items/", response_model=List[Item])
使用dict的时候可以不用pydantic模型,而仅仅定义key-value的类型。
@app.get("/keyword-weights/", response_model=Dict[str, float])

### 配置 FastAPI 中的 `strict-origin-when-cross-origin` CORS 设置 为了配置 FastAPI 应用程序中的 `strict-origin-when-cross-origin` 跨域资源共享 (CORS),可以利用 FastAPI 提供的强大中间件功能来实现这一点。具体来说,通过自定义 `CORSMiddleware` 的参数能够满足这一需求。 下面是一个具体的例子展示如何设置: ```python from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() origins = [ "http://localhost", "http://localhost:8080", ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], expose_headers=['Content-Type', 'Authorization'], ) @app.get("/") async def main(): return {"message": "Hello World"} ``` 上述代码片段展示了基本的 CORS 配置方法[^1]。然而要特别针对 `strict-origin-when-cross-origin` 进行配置,则需要进一步调整响应头以确保当请求来自不同源时只返回原始站点地址作为Referer值;而同源情况下则保持完整的URL路径不变。这可以通过修改服务器端发送给客户端的特定HTTP头部字段完成,在FastAPI中可通过扩展现有的中间件逻辑或创建新的依赖项注入器来达成目的。 对于更复杂的场景,如果希望严格控制跨站请求的安全策略并遵循 `strict-origin-when-cross-origin` 行为模式,建议深入研究官方文档以及相关RFC标准文件获取更多信息[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值