datetime:2022/09/24 15:52
author:nzb

请求参数和验证

from enum import Enum
from typing import Optional, List
from datetime import date

from fastapi import APIRouter, Path, Query, Body, Cookie, Header
from pydantic import Field
from pydantic.main import BaseModel

app3 = APIRouter()

"""Path Parameters and Number Validations 路径参数和数字验证"""


@app3.get("/path/parameters")
async def path_params01():
    return {"message": "This is message"}


@app3.get("/path/{parameters}")  # 函数的顺序就是路由的顺序
async def path_params02(parameters: str):
    return {"message": parameters}


class CityName(str, Enum):
    BeiJing = "BeiJing China"
    Shanghai = "Shanghai China"


@app3.get("/enum/{city}")  # 枚举类型的参数
async def latest(city: CityName):
    if city == CityName.BeiJing:
        return {"city_name": city, "confirmed": 1492, "death": 7}
    elif city == CityName.Shanghai:
        return {"city_name": city, "confirmed": 971, "death": 9}
    return {"city_name": city, "latest": "unknown"}


@app3.get("/files/{file_path:path}")  # 通过path parameters传递文件路径
async def filepath(file_path: str):
    return f"The file path is {file_path}"


@app3.get("/validate_path/{num}")
async def path_params_validate(
        num: int = Path(..., title="Your Number", description="不可描述", ge=1, le=10)
):
    return num


"""Query Parameters and String Validations 查询参数和字符串验证"""


@app3.get("/query")
async def page_limit(page: int = 1, limit: Optional[int] = None):  # 给了默认值就是选填的参数,没给默认值就是必填参数
    if limit:
        return {"page": page, "limit": limit}
    return {"page": page}


@app3.get("/query/bool/conversion")
async def type_conversion(param: bool = True):  # bool类型转换:yes on 1 True true会转换成true, 其它为false
    return param


@app3.get("/query/validations")  # 长度+正则表达式验证,比如长度8-16位,以a开头。其它校验方法看Query类的源码
async def query_params_validate(
        value: str = Query(..., min_length=5, max_length=10, regex="^a"),  # ...换成None就变成选填的参数
        values: List[str] = Query(["v1", "v2"], alias="alias_name")  # 多个查询参数的列表。参数别名
):
    return value, values


"""Request Body and Fields 请求体和字段"""


class CityInfo(BaseModel):
    name: str = Field(..., example="Beijing")  # example是注解的作用,值不会被验证
    country: str
    country_code: str = None  # 给一个默认值
    country_population: int = Field(default=800, title="人口数量", description="国家人口数量", ge=800)

    class Config:
        schema_extra = {
            "example": {
                "name": "Shanghai",
                "country": "China",
                "country_code": "CN",
                "country_population": 1400000000
            }
        }


@app3.post("/request_body/city")
async def city_info(city: CityInfo):
    print(city.name, city.country)  # 当在IDE中输入city.的时候,属性会自动弹出
    return city.dict()


"""Request Body + Path parameters + Query parameters 多参数混合"""


@app3.put("/request_body/city/{name}")
async def mix_city_info(
        name: str,
        city01: CityInfo,
        city02: CityInfo,  # Body可以是多个的
        confirmed: int = Query(ge=0, description="确诊数", default=0),
        death: int = Query(ge=0, description="死亡数", default=0)
):
    if name == "Shanghai":
        return {"Shanghai": {"confirmed": confirmed, "death": death}}
    return city01.dict(), city02.dict()


@app3.put("/request_body/multiple/parameters")
async def body_multiple_parameters(
        city: CityInfo = Body(..., embed=True),  # 当只有一个Body参数的时候,embed=True表示请求体参数嵌套。多个Body参数默认就是嵌套的
        confirmed: int = Query(ge=0, description="确诊数", default=0),
        death: int = Query(ge=0, description="死亡数", default=0)
):
    print(f"{city.name} 确诊数:{confirmed} 死亡数:{death}")
    return city.dict()


"""Request Body - Nested Models 数据格式嵌套的请求体"""


class Data(BaseModel):
    city: List[CityInfo] = None  # 这里就是定义数据格式嵌套的请求体
    date: date  # 额外的数据类型,还有uuid datetime bytes frozenset等,参考:https://fastapi.tiangolo.com/tutorial/extra-data-types/
    confirmed: int = Field(ge=0, description="确诊数", default=0)
    deaths: int = Field(ge=0, description="死亡数", default=0)
    recovered: int = Field(ge=0, description="痊愈数", default=0)


@app3.put("/request_body/nested")
async def nested_models(data: Data):
    return data


"""Cookie 和 Header 参数"""


@app3.get("/cookie")  # 效果只能用Postman测试
async def cookie(cookie_id: Optional[str] = Cookie(None)):  # 定义Cookie参数需要使用Cookie类,否则就是查询参数
    return {"cookie_id": cookie_id}


@app3.get("/header")
async def header(user_agent: Optional[str] = Header(None, convert_underscores=True), x_token: List[str] = Header(None)):
    """
    有些HTTP代理和服务器是不允许在请求头中带有下划线的,所以Header提供convert_underscores属性让设置
    :param user_agent: convert_underscores=True 会把 user_agent 变成 user-agent
    :param x_token: x_token是包含多个值的列表
    :return:
    """
    return {"User-Agent": user_agent, "x_token": x_token}

results matching ""

    No results matching ""