全面拥抱FasiApi ——三大参数及验证

前几天写了一篇关于 FastApi 进阶的多应用程序管理蓝图APIRouter,可能对于有些没有基础的朋友看起来会有点懵,所以后面会按照由浅及深的顺序进行更新,记得关注噢

先看下 FastAPI 有哪些突出特点,官网介绍如下:

快速:非常高的性能,性能可与NodeJSGo相媲美(感谢Starlette 和 Pydantic)。现有最快的Python框架之一
快速编码:将功能开发速度提高约200%至300%*。
更少的错误:减少约40%的人为错误(开发人员)。
直观:强大的编辑器支持,程序调试时间更少。
简易:易于使用和学习,减少阅读文档的时间。
:最小化重复代码,每个参数声明中的多个功能,减少编码错误。
健壮:获取可用于生产的代码。具有自动交互式的 API 文档。
基于标准:基于(并完全兼容)API 的开放标准:OpenAPI(以前称为Swagger)和JSON Schema

前面说过 FastApi 的一大特点是基于标准的 Python 3.6类型声明,兼具参数校验功能,这一切都要归功于 Pydantic

路径参数

路径参数即 url 路径参数,可以使用 Python 格式字符串相同语法声明路径“参数”或“变量”,例如:

from fastapi import FastAPI
app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item": item_id, "q": q}

path 参数的值 item_id 将作为参数传递给视图函数,运行命令:

uvicorn 文件名:app

默认端口是 8000,也可以指定 host 和 port , --host=0.0.0.0 --port=8008

运行之后,在浏览器种打开 http://127.0.0.1:8000/items/1,可以看到响应:

{"item":1,"q":null}

其中 item_id 被声明为 int 类型,q 为 可选参数,默认为None,所以响应中的 q 是 None

当我们通过 http://127.0.0.1:8000/items/test 去访问的时候, 可以看到一个非常友好的错误响应

{
    "detail": [
        {
            "loc": [
                "path",
                "item_id"
            ],
            "msg": "value is not a valid integer",
            "type": "type_error.integer"
        }
    ]
}

因为 path 参数 item_id 的值是 "test" 不能转为 int,这就是参加验证

查询参数

查询参数也是带在 url 地址中的,是 url 中位于 ?之后的一组键值对,以 & 字符分隔,这对爬虫朋友来说再熟悉不过了,比如下面的请求参数

data = {"test": 1, "name": "Python编程与实战"}
response = requests.get(url, params=data)

以 关键字参数 params 传过去的就是查询参数,你可以将其中的 response.url 打印出来即可看到 ?之后的键值对参数

那么在服务端 FastApi 如何来接收这种参数呢? 请看代码

from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]

运行后输入地址:http://127.0.0.1:8000/items/?skip=0&limit=10

查询参数为:

  • skip:值为 0
  • limit:值为 10
    注意这两个参数都带有默认值,可以选择只传一个

可选参数

同样,您可以通过将可选查询参数的默认值设置为来声明可选查询参数 None

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}

必需查询参数

将上面代码中的 q: str 去掉 None,则 q 变成了必须查询参数,也就是必传的,否则会提示错误

{
    "detail": [
        {
            "loc": [
                "query",
                "q"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        }
    ]
}

给大伙总结一下,在实际代码中可能会用到必需参数,默认参数,可选参数,如下:

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):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item

在这种情况下,有3个查询参数:

  • needy,是必需的 str 。
  • skip,int 默认值为 0。
  • limit,可选的 int。

其中还有一个是路径参数:item_id, str 类型

请求体参数

要发送请求正文,必须使用一个:POST, PUT,DELETE或PATCH,需导入 Pydantic 的 BaseModel

from fastapi import FastAPI
import uvicorn
from pydantic import BaseModel

app = FastAPI()

class CommonItem(BaseModel):
    token: str
    message_id: str
    to_id: str
    from_info: str
    strategy: int or str = 0  # 默认为0,可不传该参数,但是不能传空字符串
    type: str or int  # str 和 int 类型都支持
    from_id: str
    to_info: str
    content: str = None

@app.post("/test")
async def tests(item: CommonItem):
    return item

可以看到,创建了一个 CommonItem 模型,有了声明的这个模型,可以实现以下功能:

  • 以 JSON 读取请求的正文
  • 根据声明的类型,自动对参数进行转换
  • 验证数据,如果数据无效,它将返回一个清晰的错误,指出错误数据的确切位置和来源
  • 在参数中接收收到的数据 item,并能获取所有属性及所有编辑器的支持

同时,FastApi 可以自动帮我们识别请求 body 参数, 路径参数以及查询参数,并准确的获取参数数据。例如以下代码:

from fastapi import FastAPI
from pydantic import BaseModel

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

app = FastAPI()

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

上述代码,参数将被自动识别:

  • item_id,: 路径参数
  • q: 参数是一个的单一类型(如int,float,str,bool,等等)将被解释为一个查询参数
  • item: 参数声明为 Pydantic 模型的类型,则将被解释为请求 body
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容