fastapi教程(三):处理请求

环境:

  • Python 3.11
  • Windows 10
  • fastapi 0.68.0

一,路由与路由处理函数

几步就能用 fastapi 提供 api :

# main.py
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root():
    return {
   
   "message": "Hello World"}


@app.get("/hello/{name}")
async def say_hello(name: str):
    return {
   
   "message": f"Hello {
     
     name}"}


if '__main__' == __name__:
    import uvicorn
    uvicorn.run(app,port=8088)

运行项目,输出:

I:\Python\Web\FastAPI\fastApiProject1\.venv\Scripts\python.exe I:\Python\Web\FastAPI\fastApiProject1\main.py 
INFO:     Started server process [32796]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8088 (Press CTRL+C to quit)

1,导入 FastAPI:

from fastapi import FastAPI

2,创建一个 FastAPI 实例:

from fastapi import FastAPI

app = FastAPI()

3,创建一个路由:

  • 请求路径为 /
  • 接收 get 请求
from fastapi import FastAPI

app = FastAPI()

@app.get("/")

通常使用:
● POST:创建数据。使用 @app.post()
● GET:读取数据。使用 @app.get()
● PUT:更新数据。使用 @app.put()
● DELETE:删除数据。使用 @app.delete()

4,定义路由处理函数:

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root():
    return {
   
   "message": "Hello World"}

5,运行开发服务器:

$ uvicorn main:my_awesome_api --reload

浏览器访问 http://127.0.0.1:8080/ 可以获得:
在这里插入图片描述

浏览器访问 http://127.0.0.1:8088/docs 可以获得:
在这里插入图片描述

二,请求参数与表单

(一)路径参数

1,简单路径参数

from fastapi import FastAPI

app = FastAPI()

@app.get("/hello/{name}")
async def say_hello(name):
    return {
   
   "message": f"Hello {
     
     name}"}
  • 路径参数有是必须的。

访问 http://127.0.0.1:8088/hello/Jack 可以获得:
在这里插入图片描述
当路径参数缺失时,访问 http://127.0.0.1:8088/hello 将报错,因为这个残缺的路由根本不存在:
在这里插入图片描述

查看API:
在这里插入图片描述

  • API 页面就提示这个 name 参数是必须的。

2,带类型的路径参数

可在路径参数后面加上 : 类型

  • 如果不指定类型,将默认使用 str 类型。
from fastapi import FastAPI

app = FastAPI()

@app.get("/books/{book_id}")
async def say_hello(book_id: int):
    return {
   
   "message": f"book id {
     
     book_id}"}

访问 http://127.0.0.1:8088/books/123 可以获得:
在这里插入图片描述
查看API:
在这里插入图片描述

使用带类型的路径参数的最大好处就是使用 fastapi 提供的类型验证机制。

对于上面的程序,如果访问 http://127.0.0.1:8088/books/“123” 将得到一个报错:

{
   
   
    "detail": [
        {
   
   
            "type": "int_parsing",
            "loc": [
                "path",
                "book_id"
            ],
            "msg": "Input should be a valid integer, unable to parse string as an integer",
            "input": "\"123\"",
            "url": "https://errors.pydantic.dev/2.4/v/int_parsing"
        }
    ]
}
  • 这是因为 fastapi 在对 “123” 进行类型验证时,无法将它识别为 int 类型的数据,所以在报错中明确说明了原因。

3,路由访问顺序

由于 fastapi 会按照路由注册顺序来访问路由,所以可能会出现路由访问被截胡的情况:

from fastapi import FastAPI

app = FastAPI()


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


@app.get("/user/{user_id}")
async def read_user(user_id: str):
    return {
   
   "user_id": user_id}

一般来说,我们需要访问类似于 http://127.0.0.1:8088/user/some-id 这样的链接来获取具体信息。

但如果恰好有个 user_id 就是 me,即访问 http://127.0.0.1:8088/user/me 时就会得到一个期待之外的信息。

所以尤其需要注意路由的注册顺序,尽量将通用的、一般的路由放在前面。

4,使用枚举类型参数

解释一下枚举:是为变量提供一组命名的整数常量的方式。在Python中可以通过enum模块实现枚举。

枚举类型的好处是可以将一组常量的值集中在一个类中,这样可以提高代码的可读性和可维护性。

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

print(Color.RED) 			# -> Color.RED
print(Color.RED.value) 		# -> 1
print(Color(1)) 			# -> Color.RED
print(Color['RED']) 		# -> Color.RED

fastapi 允许使用枚举来对路径参数中接收到的数值进行验证:

from enum import Enum

from fastapi import FastAPI

app = FastAPI()


class ModelName(str, Enum):
    RED = 1
    GREEN = 2
    BLUE = 3


@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    if model_name == ModelName.RED:
        return {
   
   "model_name": model_name, "message": "RED"}
    if model_name == ModelName.GREEN:
        return {
   
   "model_name": model_name, "message": "GREEN"}
    if model_name == ModelName.BLUE:
        return {
   
   "model_name": model_name, "message": "BLUE"}

    return {
   
   "model_name": model_name, "message": "UNKNOWN"}


if '__main__' == __name__:
    import uvicorn
    uvicorn.run(app,port=8088)


访问:
● http://127.0.0.1:8088/models/1
● http://127.0.0.1:8088/models/2
● http://127.0.0.1:8088/models/3

5,在路径参数中包含路径

有一种常见的需求是,通过一个路由来访问服务器上的文件,例如 /files/{file_path},通常来说这个文件存放在服务器上一个具体的文件路径下,例如 home/johndoe/myfile.txt,所以这个完整的路由就是 /files/home/johndoe/myfile.txt,这需要使用路径转换器:path 来实现。

from fastapi import FastAPI

app = FastAPI()


@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
    return {
   
   "file_path": file_path}

这个 file_path 可以是文件的绝对路径,也可以是相对于路由处理函数所在文件的相对路径。
例如我们的项目结构是:
在这里插入图片描述
相对路径:
在这里插入图片描述

绝对路径:
在这里插入图片描述

6,路径参数和数值校验

可以使用 Path 为路径参数声明类型校验和元数据。

提示: 先看“查询参数和字符串校验”再回来看。
能够以与“查询参数和字符串校验”相同的方式使用 Query、Path(以及其他你还没见过的类)声明元数据和字符串校验。

(二)查询参数

路由中的路径参数和查询参数都是用于传递参数给路由处理函数的方法,主要的区别是:

  1. 路径参数是通过路由路径传递的参数,查询参数是通过请求URL的查询字符串传递的参数。
  2. 路径参数需要在路由中声明和定义,查询参数可以不需要声明。
  3. 路径参数可以出现在路由路径的任何位置,查询参数只能出现在路由路径的后面。
  4. . 路径参数通常用于必要的参数,查询参数用于可选的参数。

用场景:

  1. 路径参数用于标识一个资源或路由,如:/user/:id 用于标识用户的id。
  2. 路径参数用于 Required 参数,查询参数用于 Optional 参数。
  3. 路径参数适合少量参数,查询参数可以传递大量参数。
  4. 路径参数更美观,查询参数更灵活。

所以一般来说,必要的和结构化的参数用路径参数,可选的和非结构化的参数用查询参数。但也要根据实际场景来决定使用哪种参数。

1,标准查询参数

查询参数通过 ? 拼接在路由最后面,例如 http://127.0.0.1/path?query_param=x。
多个查询参数用 & 分割,例如 http://127.0.0.1/path?query_param1=x&query_param2=y。

from fastapi import FastAPI

app = FastAPI()

data = [
    {
   
   'name': 'John', 'age': 25},
    {
   
   'name': 'Jane', 'age': 24},
    {
   
   'name': 'Jack', 'age': 26},
]


# http://127.0.0.1:8088/users/?page_num=2&page_size=1
@app.get('/users/')
def get_users(page_num: int = 1, page_size: int = 1):
    start = (page_num - 1) * page_size
    end = start + page_size
    return data[start:end]

这里在路径操作函数中定义了两个查询参数 page_num 和 page_size,分别表示页码和每页的数据量,数据类型都是 int,分别默认值为 1 和 1。

访问 http://127.0.0.1:8088/users/?page_num=2&page_size=1 获得:
在这里插入图片描述

查看 API:
在这里插入图片描述

需要将没有「默认值」的参数放在带有「默认值」的参数之前,否则会报错。

路由处理函数是这样处理查询参数的默认值的:

  • 当 URL 中未指定任何查询参数时,所有查询参数都将使用默认值。
  • 当 URL 中指定了部分查询参数时,未指定的查询参数将使用默认值。
  • 当 URL 中指定了所有查询参数时,所有查询参数都将使用指定的值。

2,可选查询参数

可选查询参数是指被定义后可被使用,也可不被使用的查询参数,且默认值只能为 None 的查询参数。

fastapi 中的可选查询参数需要在路由处理函数中使用 Optional 类型:

import uvicorn
from typing import Optional

from fastapi import FastAPI

app = FastAPI()

data = [
    {
   
   'name': 'John', 'age': 25},
    {
   
   'name': 'Jane', 'age': 24},
    {
   
   'name': 'Jack', 'age': 26},
]


@app.get('/users/{user_name}')
def get_user(
        user_name: str,
        age: Optional[str] = None
):
    if age:
        return {
   
   'user_name': user_name, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值