初识FASTAPI(二)

本文基于Datawhale的开源学习项目wow-fullstac的子项目FastAPI
如果文中出现了错误以及不理解的地方欢迎在留言

请求体

也许直接说请求体三个字会感觉很别扭,header叫做请求头,所以请求体其实就是跟在它后面的东西了

FastAPI 使用请求体从客户端(例如浏览器)向 API 发送数据。请求体是客户端发送给 API 的数据。响应体是 API 发送给客户端的数据。API 基本上肯定要发送响应体,但是客户端不一定发送请求体。
摘自FastAPI关于请求体的介绍
在这个例子中,构造了如何计算物品的总价值并且返回的函数

import uvicorn
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.post("/items/")
async def create_item(item: Item):
    total_price = item.price + item.tax

    return {**item.model_dump(), "total_price": total_price}


if __name__ == "__main__":
    uvicorn.run(app)

构造一个请求体

import requests

url = 'http://127.0.0.1:8000/items/'

data = {
    "name": "apple",
    "description": "big red apple.",
    "price": 9.99,
    "tax": 5.01,
}

response = requests.post(url,json=data)
print(response.text)

执行结果

{"name":"apple","description":"big red apple.","price":9.99,"tax":5.01,"total_price":15.0}

路径参数、查询参数和请求体参数的异同点

特性路径参数查询参数请求体参数
位置URL路径的一部分URL查询字符串请求体(例如JSON或表单数据)
形式/items/{item_id}/items?id=123&name=abcJSON、XML、表单数据等
必需性必须提供(通常用于资源标识)可选(用于过滤、排序等)可选(通常用于复杂数据传输)
用途定位资源修改请求行为(筛选、排序等)传递复杂数据
数据类型字符串或数字(通常用于ID等)字符串或数字(通常用于查询)任意数据格式(如JSON)
示例/items/123/items?id=123&name=abc请求体中的JSON数据
FastAPI映射Path()Query()Body()

补充

查询参数和字符串校验

Query 用作查询参数的默认值即可添加校验条件
原始版本async def read_names(name: str | None = None)
带校验的版本async def read_names(name: str | None = Query(default=原始默认值,校验条件1,校验条件2,等等))
如果想要强制声明他是个必选条件参数,用...来代替原始默认值即可,也可以直接写条件不写默认值
Annotated会告诉fastapi后面的条件怎么进行校验

from typing import Annotated
@app.get("/names/")
async def read_names(name: Annotated[str,Query(min_length=3, max_length=20)]):
    result = [{"name": "Tom"}, {"name": "Alice"}]
    if name:
        result.append({"name": name})
    return result
  • 验证限制:gt, ge, lt, le, min_length, max_length, regex 等,用于字段值的范围和格式验证。
  • 描述和文档:title, description, example, examples, openapi_examples 用于生成清晰的API文档。
    这些配置项使得FastAPI能够提供强大的字段验证、文档生成以及灵活的API设计功能。

访问http://127.0.0.1:8000/names/

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

访问http://127.0.0.1:8000/names/?name=alex

[
    {
        "name": "Tom"
    },
    {
        "name": "Alice"
    },
    {
        "name": "alex"
    }
]

访问http://127.0.0.1:8000/names/?name=al

{
    "detail": [
        {
            "type": "string_too_short",
            "loc": [
                "query",
                "name"
            ],
            "msg": "String should have at least 3 characters",
            "input": "al",
            "ctx": {
                "min_length": 3
            }
        }
    ]
}

我想一次查询多个值怎么办

查询参数列表/多个值

from typing import List

@app.get("/names/")
async def read_names(names: Annotated[List[str], Query(min_length=2, max_length=20)]):
    result = [{"name": "Tom"}, {"name": "Alice"}]
    if names:
        for name in names:
            result.append({"name": name})
    return result

访问http://127.0.0.1:8000/names/?names=alex&names=bob&names=jack注意此时min_length代指了list至少需要添加两个元素

[
    {
        "name": "Tom"
    },
    {
        "name": "Alice"
    },
    {
        "name": "alex"
    },
    {
        "name": "bob"
    },
    {
        "name": "jack"
    }
]

路径参数校验

与查询参数校验类似的,我们自然也可以对路径参数进行校验
只需要对路径参数进行Path校验

@app.get("/names/{name}")
async def read_names(name: Annotated[str, Path(min_length=2, max_length=20)]):
    result = [{"name": "Tom"}, {"name": "Alice"}]
    if name:
        result.append({"name": name})
    return result

访问http://127.0.0.1:8000/names/a

{
    "detail": [
        {
            "type": "string_too_short",
            "loc": [
                "path",
                "name"
            ],
            "msg": "String should have at least 2 characters",
            "input": "a",
            "ctx": {
                "min_length": 2
            }
        }
    ]
}

多个请求体参数

现在让我们把Path Query请求体一起使用,对于下面的例子,我们需要构造的请求体需要同时包含Item User

import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


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


class Buyer(BaseModel):
    buyername: str
    location: str | None = None


@app.put("/items/{item_name}")
async def update_item(item_name: str, item: Item, buyer: Buyer):
    results = {"item_name": item_name, "item": item, "buyer": buyer}
    return results


if __name__ == "__main__":
    uvicorn.run(app)

构造请求体

import requests

url = 'http://127.0.0.1:8000/items/apple'
data = {
    "item": {"name": "apple", "description": "Big red apple", "price": 15, "tax": 5},
    "buyer": {"buyername": "Jack", "location": "the DC"},
}

response = requests.put(url,json=data)
print(response.text)

结果

'{"item_name":"apple","item":{"name":"apple","description":"Big red apple","price":15.0,"tax":5.0},"buyer":{"buyername":"Jack","location":"the DC"}}'

请求体中的单一值

还是上面的例子,假设我们还需要单独判断一下是不是苹果成熟的季节,类似的我们有Body()来校验它

import uvicorn
from fastapi import FastAPI, Body
from pydantic import BaseModel
from typing import Annotated

app = FastAPI()


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


class Buyer(BaseModel):
    buyername: str
    location: str | None = None


@app.put("/items/{item_name}")
async def update_item(
    item_name: str,
    item: Item,
    buyer: Buyer,
    month: Annotated[int, Body(ge=6, le=12, title="It's time to eat apple!")],
):
    results = {"item_name": item_name, "item": item, "buyer": buyer}
    return results


if __name__ == "__main__":
    uvicorn.run(app)

构造请求体

import requests

url = 'http://127.0.0.1:8000/items/apple'
data = {
    "item": {"name": "apple", "description": "Big red apple", "price": 15, "tax": 5},
    "buyer": {"buyername": "Jack", "location": "the DC"},
    "month":5
}

response = requests.put(url,json=data)
print(response.text)

结果

{"detail":[{"type":"greater_than_equal","loc":["body","month"],"msg":"Input should be greater than or equal to 6","input":5,"ctx":{"ge":6}}]}

声明模型属性

如果我想对tax进行限制该怎么做?
模型隶属于pydantic我们自然需要从中引入校验Field用法与Path Query一致,不再过多赘述

from pydantic import Field
class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: Annotated[float,Field(le=100)]

Cookie/Header参数

Path Query用法一致

from typing import Annotated

from fastapi import Cookie, FastAPI

app = FastAPI()


@app.get("/items/")
async def read_items(ads_id: Annotated[str | None, Cookie()] = None):
    return {"ads_id": ads_id}

访问``


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值