章工运维 章工运维
首页
  • linux
  • windows
  • 中间件
  • 监控
  • 网络
  • 存储
  • 安全
  • 防火墙
  • 数据库
  • 系统
  • docker
  • 运维工具
  • other
  • elk
  • K8S
  • ansible
  • Jenkins
  • GitLabCI_CD
  • 随笔
  • 面试
  • 工具
  • 收藏夹
  • Shell
  • python
  • golang
友链
  • 索引

    • 分类
    • 标签
    • 归档
    • 首页 (opens new window)
    • 关于我 (opens new window)
    • 图床 (opens new window)
    • 评论 (opens new window)
    • 导航栏 (opens new window)
周刊
GitHub (opens new window)

章工运维

业精于勤,荒于嬉
首页
  • linux
  • windows
  • 中间件
  • 监控
  • 网络
  • 存储
  • 安全
  • 防火墙
  • 数据库
  • 系统
  • docker
  • 运维工具
  • other
  • elk
  • K8S
  • ansible
  • Jenkins
  • GitLabCI_CD
  • 随笔
  • 面试
  • 工具
  • 收藏夹
  • Shell
  • python
  • golang
友链
  • 索引

    • 分类
    • 标签
    • 归档
    • 首页 (opens new window)
    • 关于我 (opens new window)
    • 图床 (opens new window)
    • 评论 (opens new window)
    • 导航栏 (opens new window)
周刊
GitHub (opens new window)
  • python

    • python基础

    • FastAPI

      • FastAPI-快速入门1
      • FastAPI-路由2
        • 查询路径参数和参数校验
          • 第一种访问的情况:
          • 第二种访问情况:
          • 第三种访问情况:
        • 多路径和查询参数
        • 路径参数和查询参数的必选和可选
        • 路径参数的枚举
        • 查询参数Query参数的其他校验
        • 查询参数Query参数多值列表
        • 路径参数的其他校验方式
      • FastApi-参数提交3
      • FastApi-响应报文
      • FastApi-错误处理
      • FastApi-中间件
      • FastApi-跨域处理
      • 依赖注入之Depends
    • python每日练习脚本

    • python3给防火墙添加放行
    • python生成部署脚本
    • python将多个文件内容输出到一个文件中
    • 使用 Aligo 定时备份服务器文件
    • python监控日志文件并发送钉钉告警
    • python监控数据库脚本并发送钉钉告警
    • 使用python编写自动化发布脚本
    • 查询redis列表某个元素
    • centos7安装python3
    • python环境管理工具介绍
    • conda安装和镜像源配置
    • pip更换国内源
    • python爬虫
    • python环境启动服务报错缺少glibc库版本
    • 监控目录或文件变化
    • 批量更改文件
    • python引用数据库
  • shell

  • go

  • 编程
  • python
  • FastAPI
章工运维
2024-11-27
目录

FastAPI-路由2

# 一、概述

路由方法有 GET, POST, PUT, PATCH, DELETE 和 OPTIONS。

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.post("/")
@app.put("/")
@app.delete("/")
@app.get("/")
@app.options("/")
@app.head("/")
@app.patch("/")
@app.trace("/")
async def root():
    return {"message": "Hello 454533333343433World"}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 二、路由Route上参数获取和校验

一般我们的路由分会静态和动态,静态路由就是参数是固定写死,也就是访问地址是写死的,而动态地址,就是需要动态的生成,类似简书的博文的地址94710ed35b92就是动态,其实和Bottle和Flask一样。

https://www.jianshu.com/p/94710ed35b92

代码如下:

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id):
    return {"item_id": item_id}
if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10

上述的示例代码中的item_id 就是一个动态的参数,你可以随意传一个进来。

http://127.0.0.1:8000/items/ask

726091c3b771485c.png

然后就是和bottle(微型Web框架)一样也可以对传入的参数进行数据验证的定义: 如:

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11

item_id: int 这种情况item_id必须是可以转为int类似的数据,否则,肯定会报错!

http://127.0.0.1:8000/items/ask

c5b529c81adf9536.png

它会给出提示,必须是int类型。返回的HTTP状态码为422

关于路由覆盖问题: 如下两个路由地址:

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/users/me")
async def read_user_me():
    return {"user_id": "the current user"}

@app.get("/users/{user_id}")
async def read_user(user_id: str):
    return {"被优先匹配到:": user_id}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

上面两个路由同时存在的话,会按照匹配规则进行匹配。什么意思呢?

@app.get("/users/me") 表示精确匹配

@app.get("/users/{user_id}") 表示模糊匹配

下面我来验证一下。

http://127.0.0.1:8000/users/me

4d976367b4bfcf46.png

可以看到,它匹配了是第一条。注意:只有正常情况下,才会返回HTTP 200

http://127.0.0.1:8000/users/123

e91a7029ccc85e7d.png

发现它是匹配的第2个路径。

# 查询路径参数和参数校验

关于查询参数,其实就是在使用POSTMAN 提交的时候的参数信息: 如:

http://127.0.0.1:8000/items/?skip=0&limit=10
1

skip=0&limit 就是所谓的查询参数。

import uvicorn
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]

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13

# 第一种访问的情况:

http://127.0.0.1:8000/items/

96a1c85a1c8e09a0.png

我们发现,它返回的是list所有数据。这是为什么呢?来,我来细细品一下代码。

在这个url中,并没有传入参数skip和limit,那么它会使用默认值,分别是0,100

那么fake_items_db[skip: skip + limit] 等同于fake_items_db[0:10]

看到这里,学过python基础知识的,应该明白,这是列表切片。

# 第二种访问情况:

http://127.0.0.1:8000/items/?skip=1

80abed8dae49b7e1.png

返回了最后2条数据,第一条没有显示。因为此时fake_items_db[skip: skip + limit] 等同于fake_items_db[1:10]

# 第三种访问情况:

http://127.0.0.1:8000/items/?skip=abc

d05fda93a899830b.png

提示错误信息,值不是整形,HTTP状态码为:422

# 多路径和查询参数

所谓的多路径和查询参数就是URL上包含了有动态的参数,还有需要通过&分隔符提交的参数,这情况,通常再GET提交的中也很常见,那么如何处理呐?

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: str = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

请求:

http://127.0.0.1:8000/users/123456/items/items_xinxiid/?q=assa&short=True

206b3f71abd579f4.png

注意:item.update 是python字典的一个语法。存在即更新,不存在,即添加。

其他逻辑我就不解释了,仔细看也能明白。

请求:

http://127.0.0.1:8000/users/123456/items/items_xinxiid/?q=assa&short=False

dff48d8f27eb6efd.png

由于short=False,因此description值做了更新操作。

# 路径参数和查询参数的必选和可选

参数的可选和必选主要是通过是否给默认值来决定的,如:

import uvicorn
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

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12

上述的代码中 needy 没有给与默认的值,当个没提交这个值的时候,会提示错误:

http://127.0.0.1:8000/items/123456

c82877546c3b9278.png

还可以定义可选参数和必选的参数的提交类型: 其中还可以使用Optional来定义需要提交的数据类型: 如:

import uvicorn
from fastapi import FastAPI
from typing import Optional

app = FastAPI()

@app.get("/items/{item_id}")
async def read_user_item(item_id: str, limit: Optional[int] = None):
    item = {"item_id": item_id, "limit": limit}
    return item

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13

我们把查询参数limit规定为了int类型,但是它是可选的的参数,设置为了None:

http://127.0.0.1:8000/items/ask

93aa466617415a0d.png

如果传入的参数类型不对,就会报错

http://127.0.0.1:8000/items/ask?limit=422w

81bc2e78ef3eb691.png

# 路径参数的枚举

import uvicorn
from fastapi import FastAPI
from enum import Enum

app = FastAPI()

class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"

@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
    if model_name == ModelName.alexnet:
        return {"model_name": model_name, "message": "Deep Learning FTW!"}
    if model_name.value == "lenet":
        return {"model_name": model_name, "message": "LeCNN all the images"}
    return {"model_name": model_name, "message": "Have some residuals"}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

访问地址:

http://127.0.0.1:8000/model/alexnet

0090622a693df610.png

可以发现,它匹配了第一条规则。

# 查询参数Query参数的其他校验

在以前通常是使用wtform来定义提交的字段信息的类似或可选或长度类型。在Fastapi里面,我们是通过: from fastapi import FastAPI, Query 中的Query来定义,如:

import uvicorn
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(q: str = Query(None, min_length=3,max_length=50,regex="^fixedquery")):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

注意:参考文章中有一个小错误,regex必须在Query里面才能生效。

参数解释:

q: str = Query(None, min_length=3,max_length=50,regex="^fixedquery") 
意思是:q参数是可选的参数,但是如果填写的话,最大长度必须是小于50内,且最小的长度
必须大于3: 且需要符合regex的匹配

当然None可以修改为其他默认值,可以写如:

q: q: str = Query('xiaozhong', min_length=3,
max_length=50,regex="^fixedquery"))

注意:如果正则为^fixedquery$,表示精确匹配,q必须是fixedquery才行。前后左右多一点都不行。

为了下面的测试,我去掉了$

http://127.0.0.1:8000/items/

a73010055038f049.png

传q的情况下且长度大于50:

http://127.0.0.1:8000/items/?q=fixedquery333333333333333333333333333333333333333333

5feacade40d0584c.png

传q的情况下且长度小于3:

http://127.0.0.1:8000/items/?q=fixedquery333

99b2c0bbe384e483.png

查询参数Query的参数正则校验

http://127.0.0.1:8000/items/?q=433

1abbab3ef4664d67.png

# 查询参数Query参数多值列表

一般在我们的接口中很少说同一个参数提交多个值如:

http://127.0.0.1:8000/items/?q=foo&q=bar

但也不排查这种情况的存在,所以也可以定义我们的参数类似必须是列表的形式:

import uvicorn
from fastapi import FastAPI, Query
from typing import List

app = FastAPI()


@app.get("/items/")
async def read_items(q: List[str] = Query(["foo", "bar"])):
    # <!--也可以使用list直接代替List[str]:-->
    query_items = {"q": q}
    return query_items

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

默认值:

http://127.0.0.1:8000/items/

21722f44e4a7f025.png

非默认值:

http://127.0.0.1:8000/items/?q=123&q=456

b4b5b9160389a763.png

# 路径参数的其他校验方式

对于查询参数可以通过Query,同样对于路径参数也可以使用Fastapi自带的Path来进行校验。

import uvicorn
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: int = Path(..., title="The ID of the item to get")
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

http://127.0.0.1:8000/items/11?q=22

2b5cfaed344d9ae1.png

对于路径参数校验中,还可以对item_id进行大于或等于的校验如:

import uvicorn
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
        *, item_id: int = Path(..., title="The ID of the item to get", ge=1), q: str):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在上面代码意思是,item_id必须是整数,而且必须大于等于1。其中ge=1表示大于等于1

传入0就会报错

http://127.0.0.1:8000/items/0?q=aa

e443f626d25b4163.png


原文链接 (opens new window)

微信 支付宝
上次更新: 2024/12/13, 12:36:19

← FastAPI-快速入门1 FastApi-参数提交3→

最近更新
01
shell脚本模块集合
05-13
02
生活小技巧(认知版)
04-29
03
生活小技巧(防骗版)
04-29
更多文章>
Theme by Vdoing | Copyright © 2019-2025 | 点击查看十年之约 | 鄂ICP备2024072800号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式