一、查询参数

1.1 请求参数

路径函数中声明不属于路径参数的其他函数参数时,它们将被自动解释为"查询字符串"参数,就是 url? 之后用&分割的 key-value 键值对。

比如这里的路径参数就只有:{kd}

而search_jobs函数中定义的参数(city,xl)不在路径参数(路径参数只有{kd})

查询参数是:city,xl

@app.get("/jobs/{kd}")
def search_jobs(kd: str, city: Union[str, None] = None, xl: Union[str, None] = None):  # 有默认值即可选,否则必选
    if city or xl:
        return {"kd": kd, "city": city, "xl": xl}
    return {"kd": kd}

Union[str, None],表示该参数数据,可以为字符串类型或者空值
在这里插入图片描述
在这个例子中,函数参数 cityxl 是可选的,并且默认值为 None

自python3.5开始,PEP484为python引入了类型注解(type hints),typing的主要作用有:

  1. 类型检查,防止运行时出现参数、返回值类型不符。
  2. 作为开发文档附加说明,方便使用者调用时传入和返回参数类型。
  3. 模块加入不会影响程序的运行不会报正式的错误,pycharm支持typing检查错误时会出现黄色警告。

type hints主要是要指示函数的输入和输出的数据类型,数据类型在typing 包中,基本类型有str list dict等等,

Union 是当有多种可能的数据类型时使用,比如函数有可能根据不同情况有时返回str或返回list,那么就可以写成Union[list, str]
Optional 是Union的一个简化, 当 数据类型中有可能是None时,比如有可能是str也有可能是None,则Optional[str], 相当于Union[str, None]

1.2 必选查询参数

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
    item = {"item_id": item_id, "needy": needy}
    return item

liru 这里的查询参数 needy 是类型为 str 的必选查询参数。

在浏览器中打开如下 URL:

http://127.0.0.1:8080/items/foo

因为路径中没有必选参数 needy,返回的响应中会显示如下错误信息:

{
  "detail": [
    {
      "type": "missing",
      "loc": [
        "query",
        "needy"
      ],
      "msg": "Field required",
      "input": null
    }
  ]
}

needy 是必选参数,因此要在 URL 中设置值:

http://127.0.0.1:8000/items/foofoofoo?needy=sunsunsun

这样就正常了:

{
    "item_id": "foofoofoo",
    "needy": "sunsunsun"
}

把一些参数定义为必选,为另一些参数设置默认值,再把其它参数定义为可选,这些操作都是可以正常实现的

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(
    item_id: str, needy: str, skip: int = 0, limit: int | None = None
):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item

本例中有 3 个查询参数:

  • needy,必选的 str 类型参数
  • skip,默认值为 0int 类型参数
  • limit,可选的 int 类型参数

二、请求体数据

2.1 请求体

当你需要将数据从客户端(例如浏览器)发送给 API 时,你将其作为「请求体」发送。请求体是客户端发送给 API 的数据。响应体是 API 发送给客户端的数据。

FastAPI 基于 PydanticPydantic 主要用来做类型强制检查(校验数据)。不符合类型要求就会抛出异常。

对于 API 服务,支持类型检查非常有用,会让服务更加健壮,也会加快开发速度,因为开发者再也不用自己写一行一行的做类型检查。

安装上手pip install pydantic

从 pydantic 中导入 BaseModel:

# app03.py

from fastapi import APIRouter
from pydantic import BaseModel, Field, validator, ValidationError
from datetime import date
from typing import List, Union, Optional


app03 = APIRouter()


class Addr(BaseModel):  # 地址信息参数必须是字符串类型
    province: str
    city: str


class User(BaseModel):  # 把数据模型声明为继承 BaseModel 的类。
	# 使用 Python 标准类型声明所有属性: 
    name: str = 'root'
    age: int = Field(default=0, ge=0, le=100)  # 0 ~ 100
    birth: Union[date, None] = None
    friends: List[int] = []
    description: Optional[str] = None
    addr: Addr  # 使用上面定义的Addr类

    @validator('name')  # 正则匹配功能
    def name_must_alpha(cls, value):  # 函数名叫什么无所谓
        assert value.isalpha(), 'name must be alpha!'
        return value  # 必须与有返回值


class Data(BaseModel):
    data: List[User]  # 组合嵌套使用。调用User类,列表类型


@app03.post("/user")
async def user(user: User):
    print(user)
    print(user.name, user.birth, type(user))
    print(user.dict())
    return user


@app03.post("/data")
async def data(data: Data):
    return data

与声明查询参数一样,包含默认值的模型属性是可选的,否则就是必选的。把默认值设为 None 可使其变为可选。

说明

@app03.post("/user")
async def user(user: User):
    print(user)
    print(user.name, user.birth, type(user))
    print(user.dict())
    return user

使用与声明路径和查询参数相同的方式,把它添加至路径操作

并把其类型声明为你创建的模型

main.py文件

from fastapi import FastAPI
from apps.app03 import app03


import uvicorn

app = FastAPI()
app.include_router(app03, prefix="/demo", tags=["03 请求响应"])


if __name__ == '__main__':
    uvicorn.run("main:app", port=8080, debug=True, reload=True)

正常访问请求 /user 路由
在这里插入图片描述
数据类型与定义不一致时
在这里插入图片描述

访问 /data 路由
在这里插入图片描述
和声明查询参数时一样,当一个模型属性具有默认值时,它不是必需的。否则它是一个必需属性。将默认值设为 None 可使其成为可选属性。

FastAPI 会自动将定义的模型类转化为JSON Schema,Schema 成为 OpenAPI 生成模式的一部分,并显示在 API 交互文档中,查看 API 交互文档如下,该接口将接收application/json类型的参数。

FastAPI 支持同时定义 Path 参数、Query 参数和请求体参数,FastAPI 将会正确识别并获取数据。

参数在 url 中也声明了,它将被解释为 path 参数

参数是单一类型(例如int、float、str、bool等),它将被解释为 query 参数

参数类型为继承 Pydantic 模块的BaseModel类的数据模型类,则它将被解释为请求体参数

2.2 请求体 + 路径参数

可以同时声明路径参数和请求体

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None


app = FastAPI()


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    return {"item_id": item_id, **item.model_dump()}

2.3 请求体 + 路径 + 查询参数

也可以同时声明请求体、路径和查询参数。

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None


app = FastAPI()


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: str | None = None):
    result = {"item_id": item_id, **item.model_dump()}
    if q:
        result.update({"q": q})
    return result

函数参数按如下规则进行识别:

  • 如果该参数也在路径中声明了,它就是路径参数。
  • 如果该参数是(int、float、str、bool 等)单一类型,它会被当作查询参数。
  • 如果该参数的类型声明为 Pydantic 模型,它会被当作请求体。
FastAPI 会根据默认值 = None 知道 q 的值不是必填的。

str | None 并不是 FastAPI 用来判断是否必填的依据;是否必填由是否有默认值 = None 决定。

但添加这些类型注解可以让你的编辑器提供更好的支持并检测错误。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐