一、路径操作

1.2 路径操作装饰器

fastapi支持各种请求方式:

@app.get()
@app.post()
@app.put()
@app.patch()
@app.delete()
@app.options()
@app.head()
@app.trace()
from typing import Union
from fastapi import FastAPI

app = FastAPI()


@app.get("/get")
def get_test():
    return {"method": "get方法"}


@app.post("/post")
def post_test():
    return {"method": "post方法"}


@app.put("/put")
def put_test():
    return {"method": "put方法"}


@app.delete("/delete")
def delete_test():
    return {"method": "delete方法"}

if __name__ == '__main__':
    uvicorn.run("路径操作装饰器方法:app", port=8080, debug=True, reload=True)

比如第一个「路径操作函数」:

  • 路径:是 /get。
  • 操作:是 get。
  • 函数:是位于「装饰器」下方的函数(位于 @app.get(“/”) 下方)。
    在这里插入图片描述

1.2 路径操作装饰器参数:

@app.post(
    "/items/{item_id}",
    response_model=Item,  # 响应类型,其中有过滤功能,报错时返回500,内部错误
    status_code=status.HTTP_200_OK,  # 用于响应的默认状态码
    tags=["AAA"],  # 接口标签列表,位置处于接口的上方
    summary="this is summary",  # 接口总结性内容
    description="this is description",  # 接口详情内容描述
    response_description= "this is response_description",  # 响应结果描述
    deprecated=False,   # 接口是否废弃
)

示例一代码:

# 路径操作装饰器方法的参数.py

from fastapi import FastAPI
import uvicorn

app = FastAPI()

@app.post("/items", tags=["这是items测试接口"],
          summary="items测试 总结性内容",  # 接口总结性内容
          description="items测试 接口详情描述",  # 接口详情内容描述
          response_description="这是响应描述,200代表成功",
          # deprecated=True,  # 接口是否废弃
          )
def get_test():
    return {"items": "items数据"}

if __name__ == '__main__':
    uvicorn.run("路径操作装饰器方法的参数:app", port=8080, debug=True, reload=True)

用浏览器打开 http://127.0.0.1:8080/docs, API文档内容:
在这里插入图片描述

示例二代码:

from fastapi import FastAPI
app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}
在路径 / 和 /items/{item_id} 接收 HTTP 请求。
以上两个路径都接受 GET 操作(也称为 HTTP 方法)。
路径 /items/{item_id} 有一个应为 int 的路径参数 item_id。
路径 /items/{item_id} 有一个可选的 str 类型查询参数 q。

用浏览器打开 http://127.0.0.1:8080/items/5?q=somequery

{"item_id": 5, "q": "somequery"}

1.3 路径动态参数

其实上面的示例二就是该动态参数的方式。
简单示例:接口中路径变为动态,根据用户输入的值,进行查询

# 路径参数.py

import uvicorn
from fastapi import FastAPI
app = FastAPI()


@app.get("/query_user/{user_id}", tags=["获取用户ID"], summary="输入id值,查询用户id")
async def query_user(user_id: int):  # 默认是字符串类型,这里转为int
    print("user_id的类型", type(user_id))
    return {"code": 200, "user_id": user_id}


@app.get("/query_article/{article_id}", tags=["获取文章ID"], summary="输入id值,查询文章id")
async def query_article(article_id: int):  # 默认是字符串类型,这里转为int
    print("article_id的类型", type(article_id))
    return {"code": 200, "article_id": article_id}


if __name__ == '__main__':
    uvicorn.run("路径动态参数:app", port=8080, debug=True, reload=True)

在这里插入图片描述

1.4 相同路径下优先级匹配

若是我们定义有2个相同路由时,路由有优先级,从上向下匹配。
但是如果配合上动态参数呢,比如我们传入的参数整体的路由正好匹配上了A路由,这时是匹配当前动态参数的B路由呢,还是匹配A路由呢,
下面示例:

# 路径动态参数.py
import uvicorn
from fastapi import FastAPI
app = FastAPI()


# 路由顺序是有影响的
@app.get("/user/me", tags=["获取当前用户名"])
async def read_user_me():
    return {"code": 200, "username": "Current user is 【rain】"}


@app.get("/user/{username}", tags=["查询其他用户名"])
async def read_other_user(username: str):
    return {"code": 200, "username": f"Other user is 【{username}】"}


if __name__ == '__main__':
    uvicorn.run("路径动态参数:app", port=8080, debug=True, reload=True)

若查询中{username}的值=me,那么会优先走上面的路由(/user/me),还是走(/user/{username})?

访问后查看结果:http://127.0.0.1:8080/user/me
在这里插入图片描述
结果: 优先走上面的路由(/user/me),这也是因为路由有优先级,从上向下匹配。

我们可以将函数换个顺序再次查看

# 路径动态参数.py

import uvicorn
from fastapi import FastAPI
app = FastAPI()


@app.get("/user/{username}", tags=["查询其他用户名"])
async def read_other_user(username: str):
    return {"code": 200, "username": f"Other user is 【{username}】"}


@app.get("/user/me", tags=["获取当前用户名"])
async def read_user_me():
    return {"code": 200, "username": "Current user is 【rain】"}


if __name__ == '__main__':
    uvicorn.run("路径动态参数:app", port=8080, debug=True, reload=True)

在这里插入图片描述

二、路由分发

2.1 include_router

将路径整合并分发,便于管理
比如,
将带有 /shop/xxx 的路由,都属于购物中心接口。
将带有 /user/xx 的路由,都属于用户中心接口。
这样归属完一类之后,再写路由就在某一类下写,就容易区分,而不是都写在一个页面中,如果有上百上千个,这样做明显是不合理的。

目录结构

|-- apps
	|--app01
		|--__init__.py
		|--urls.py
	|--app02
		|--__init__.py
		|--urls.py
|-- main.py

在这里插入图片描述
下面在创建文件夹,表示某一个类的路由内容,这样就比较灵活了
app01.urls.py

from fastapi import APIRouter

user = APIRouter()


@user.post("/login",
           summary="这是一个登录页",
           description="这是登录页的具体描述",  # 接口详情内容描述
           response_description="这是登录页响应结果的描述",
           )
def login():
    return {"code": 200, "user": "登录"}


@user.post("/index",
           summary="这是一个首页",
           description="这是首页的具体描述",  # 接口详情内容描述
           response_description="这是首页响应结果的描述",
           )
def index():
    return {"code": 200, "message": "首页"}

app02.urls.py

from fastapi import APIRouter

shop = APIRouter()


@shop.post("/reg",
           summary="这是一个reg页",
           description="这个接口不再使用,弃用状态",  # 接口详情内容描述
           deprecated=True,  # 接口是否废弃
           )
def login():
    return {"code": 404, "user": "reg"}


@shop.post("/buy",
           summary="这是一个购买商品的页面",
           )
def index():
    return {"code": 200, "message": "购买"}

最后创建一个main.py

from fastapi import FastAPI
import uvicorn
from apps.app01.urls import user
from apps.app02.urls import shop

app = FastAPI()


# 将路径整合并分发,便于管理
app.include_router(user, prefix="/user", tags=["用户中心接口"])
app.include_router(shop, prefix="/shop", tags=["购物中心接口"])

if __name__ == '__main__':
    uvicorn.run("main:app", port=8080, debug=True, reload=True)
    # 接口文档内容:http://127.0.0.1:8080/docs
app.include_router(user, prefix="/user", tags=["用户中心接口"])
第一个参数:路由对象
第二个参数:路由都会加上该前缀
第三个参数:表示属于哪一类,打上标签名称。

文档展示如下:
在这里插入图片描述

测试:
在这里插入图片描述

Logo

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

更多推荐