【FastAPI后台API 七】GET和POST请求参数接收以及验证

FastAPI http请求参数的接收

我最开始接触FastAPI的时候,最搞不懂的就是POST方式是如何接收参数的。

声明

移步博客园或个人网站 https://www.cnblogs.com/CharmCode/p/14191108.html

GET请求参数

GET方式的参数有两种,一种是路径参数,一种是查询参数。举个例子来说明两者的区别

  • 路径参数 官方文档 https://fastapi.tiangolo.com/tutorial/path-params/
from fastapi import FastAPI

app = FastAPI()

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

这种是直接写在请求路径里面的item_id,就是路径参数,(但是个人不喜欢用)

请求示例url, 比如本地8000端口启动 http://127.0.0.1:8000/items/10
启动方式,如文件名为main.py(不限制但是必须和启动的文件名对应) 都是测试环境启动
安装pip install uvicorn才能使用

# 在最下面加上 这一句
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

或者用命令行启动 注意:得和main.py在同一文件目录下

uvicorn main:app --host=127.0.0.1 --port=8000 --reload
  • 查询参数 官方文档 https://fastapi.tiangolo.com/tutorial/query-params/
from fastapi import FastAPI

app = FastAPI()

@app.get("/bar")
async def read_item(name: str, age: int=18): # tip: 和python默认参数一样,有默认参数写在后面
    return {"name": name, "age": age}

这种nameage就是查询参数方式GET请求,也就是最常见的?&符号请求方式了
如上请求示例url: http://127.0.0.1:8000/bar?age=22&name=foo

路径参数和查询参数,参数验证的区别

路径参数使用 Path 查询参数使用Query, 可以查看Path和Query的源码,其实现方式和使用参数方式都差不多,我理解的就是用来验证不用的请求方式的参数。参数有很多验证规则。

from typing import Optional
from fastapi import FastAPI, Path, Query

app = FastAPI()

@app.get("/bar/{foo}")
async def read_item(
        foo: int = Path(1, title='描述'),
        age: int = Query(..., le=120, title="年龄"),
        name: Optional[str] = Query(None, min_length=3, max_length=50, regex="^xiao\d+$")
):
    return {"foo": foo, "age": age, "name": name}

上述GET请求合法的请求url是


http://127.0.0.1:8000/bar/123?age=18  # Query(...)表示没有默认参数必须得传
# or或者
http://127.0.0.1:8000/bar/123?age=18&name=xiao1  # name可以不传,传了就要符合正则的限制xiao开头数字结尾

以上验证参数简单描述
le 验证数字age最大不超过120
min_length 验证name最短3个字符
max_length 验证name最长50个字符
regex 这个就是正则验证 必须是xiao开头数字结尾(当然前提你得熟悉正则)
还有就是Query(..., le=120) … 表示没有默认参数,必须要传。

def Query(  # noqa: N802 关于FastAPI源码里面noqa我搜了下,是No Quality Assurance 见issues https://github.com/PyCQA/pycodestyle/issues/476 还是还是Guido提问的
    default: Any,
    *,
    alias: str = None,    # 请求参数别名 如上name字段 Query(..., alias="N-A-N-E") 个人一般认为headers里面得参数用的多比如headers里面自定义的 X-Token
    # 接收name的url就得是这样 http://127.0.0.1:8060/bar/123?age=18&N-A-N-E=xiaoming
    title: str = None,
    description: str = None,  
    gt: float = None,
    ge: float = None,
    lt: float = None,
    le: float = None,
    min_length: int = None,
    max_length: int = None,
    regex: str = None,
    deprecated: bool = None,   # True表示将要是废弃的接口
    **extra: Any,
)

更多验证方式直接查看Query或者Path源码,看到参数名字,如上Query源码,简单的英语就知道是干什么用的。如果还不清楚查看官网

异常处理

额,我感觉我博客顺序有点问题,应该先讲参数处理再说异常捕获的,详细异常捕获可以查看前一个博客。

比如上面的 http://127.0.0.1:8000/bar/123 这个就是参数验证失败了,会触发RequestValidationError异常

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

捕获参数异常

from typing import Optional
from fastapi import FastAPI, Request, Path, Query
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"参数不对{request.method} {request.url}") # 可以用日志记录请求信息,方便排错
    return JSONResponse({"code": "400", "message": exc.errors()})

@app.get("/bar/{foo}")
async def read_item(
        foo: int = Path(1, title='描述'),
        age: int = Query(..., le=120, title="年龄"),
        name: Optional[str] = Query(None, min_length=3, max_length=50, regex="^xiao\d+$")
):
    return {"foo": foo, "age": age, "name": name}

这样的话,就可以捕获,然后按照自己定义的方式响应json格式。
还是上面的http://127.0.0.1:8000/bar/123 就会如下返回

{
    "code": "400",
    "message": [
        {
            "loc": [
                "query",
                "age"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        }
    ]
}

如果还不熟悉Python3.6之后的typing模块就要好好补补了:typing模块官网传送门 https://docs.python.org/zh-cn/3/library/typing.html

POST 请求参数

还是上面那个例子改成POST请求,与Query或者Path不一样的就是,使用Body函数来限制参数格式, 如下: Body和Query,Path用法基本是一样的。

embed=True 意思是请求体中,使用json key-value形式, 参考官网

from fastapi import FastAPI, Request, Body
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

app = FastAPI()


@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"参数不对{request.method} {request.url}")
    return JSONResponse({"code": "400", "message": exc.errors()})


@app.post("/bar")
async def read_item(
        foo: int = Body(1, title='描述', embed=True),
        age: int = Body(..., le=120, title="年龄", embed=True),
        name: str = Body(..., regex="^xiao\d+$", embed=True)
):
    return {"foo": foo, "age": age, "name": name}

正确的请求方式是 注意header请求头里面"accept: application/json"

curl -X POST "http://127.0.0.1:8000/bar" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"foo\":1,\"age\":2,\"name\":\"333\"}"

Python requests发送请求

import requests

res = requests.post("http://127.0.0.1:8000/bar", json={"foo": 1, "age": 12, "name": "xiao123"})
print(res.json())  # {'foo': 1, 'age': 12, 'name': 'xiao123'}

上述demo只能接收application/json json方式的参数,表单POST请求的方式是接收不到参数的,如form-data 只能使用Form接收,下面是示例:
注意必须安装 pip install python-multipart 才能接收Form参数官网传送门

from fastapi import FastAPI, Form

app = FastAPI()

@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
    return {"username": username}
POST参数验证

POST方式除了使用Body方法来验证外,更多的时候是使用的pydantic 这个库来验证的
比如以上的POST请求参数就可以换成一下例子

import re
from typing import Optional
from fastapi import FastAPI, Request, Body
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel, validator, conint, constr

app = FastAPI()


class UserInfo(BaseModel):
    foo: int = 1
    age: conint(le=120) = 18
    # 这里 regex验证 我不知道为什么PyCharm提示语法错误
    name: constr(min_length=5, max_length=10, regex=r"^xiao\d+$")  
	
	# 复杂的验证一般用这个
    @validator('name')
    def name_re(cls, v):
        # 自定义验证 正则验证name字段 等同于上面的正则验证
        if not re.match(r"^xiao\d+$", v):
            # 抛出 ValueError pydantic接收到后会向外抛出 ValidationError
            raise ValueError("name格式验证错误")
        return v

# FastAPI RequestValidationError本就是继承的ValidationError, 会捕获到请求参数异常错误
@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"参数不对{request.method} {request.url}")
    return JSONResponse({"code": "400", "message": exc.errors()})


@app.post("/bar")
async def read_item(
        user_info: UserInfo
):
    return {"foo": user_info.foo, "age": user_info.age, "name": user_info.name}


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

上述例子正确访问方式应是

curl -X POST "http://127.0.0.1:8000/bar" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"foo\":1,\"age\":2,\"name\":\"xiao1\"}"
关于POST form表单参数接收

记得一定要安装 这个库,否则接收不到值, 其他的用法都差不多。

pip install python-multipart

参考官网 https://fastapi.tiangolo.com/tutorial/request-forms/ 这里不在赘述,用法差不多

总结

  • Path方法获取请求路径里面的参数如 http://127.0.0.1:8000/bar/123
  • Query方法获取请求路径后面的查询参数如 http://127.0.0.1:8000/bar?name=xiaoming&age=18
  • Body方法获取请求体里面的参数,前提是请求头得用accept: application/json

当然我POST例子中只列举了获取Body参数的例子,也可以获取路径参数Path和查询参数Query

完整代码GitHub地址

更多FastAPI信息可以关注人网站

见个人网站 https://www.charmcode.cn/article/2020-07-23_fastapi_get_post

  • 15
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 使用 APITest 平台(旧名为 APIPOST)定义 API请求参数和返回参数非常简单。具体步骤如下: 1. 在 APITest 平台上创建一个项目,并在项目中创建一个接口。 2. 进入接口编辑页面,在右侧的请求参数和返回参数编辑区域,可以看到一些默认的参数,包括请求方法、请求 URL、请求头、请求体等。 3. 点击“添加参数”按钮,可以添加自定义的请求参数或返回参数。在弹出的对话框中,填写参数名称、参数类型、是否必填等信息,并保存。 4. 在请求参数和返回参数列表中,可以对已有的参数进行编辑、删除等操作。 5. 定义完成后,可以点击“保存”按钮保存接口的配置信息。 通过以上步骤,就可以在 APITest 平台上定义 API请求参数和返回参数了。 ### 回答2: 使用APIPost7定义API请求参数和返回参数可以通过以下步骤进行: 1. 首先,确保已经安装并导入APIPost7的依赖库。APIPost7是一款非常强大的前端API接口调试与管理工具,通过它可以轻松地定义和测试API接口。 2. 打开APIPost7的界面,点击创建新的接口,以开始定义一个API。 3. 在接口创建界面中,填写接口的基本信息,包括接口名称、URL和请求方法。这些信息将帮助APIPost7知道如何发送请求和处理返回。 4. 在请求参数的部分,你可以点击添加参数来定义接口的请求参数。根据你的需求,可以定义参数的名称、类型(例如字符串、整数或布尔值等)、是否必需、参数位置(例如URL中的查询参数请求体中的参数等)以及默认值等。 5. 在返回参数的部分,你同样可以点击添加参数来定义接口的返回参数。你可以定义参数的名称、类型、说明等。这些信息将帮助你说明接口的返回数据结构。 6. 定义完接口的请求参数和返回参数后,你可以保存接口并进行测试。APIPost7提供了一系列的请求功能,包括发送请求、查看请求结果和调试接口。通过这些功能,你可以验证接口定义的正确性和可用性。 总结起来,使用APIPost7定义API请求参数和返回参数是一个非常简单和直观的过程。通过与APIPost7的交互,我们可以定义接口的各项细节,并验证接口的正确性。同时,APIPost7还提供了丰富的测试工具和功能,方便我们进行接口的调试和测试。 ### 回答3: 使用 APIPOST7 定义 API请求参数和返回参数需要按照以下步骤进行: 1. 首先,安装 APIPOST7 工具并打开它。 2. 创建一个新的 API 项目或者选择一个已有的项目。 3. 在 API 项目中,点击“添加接口”按钮来定义一个新的接口。 4. 在接口定义页面,选择请求方法(如 GET、POST、PUT、DELETE 等)和请求地址(URL)。 5. 在请求参数部分,点击“添加参数”按钮来定义每个请求参数。可以指定参数的名称、类型(如 string、integer 等)、是否必需、默认值等属性。 6. 在返回参数部分,同样点击“添加参数”按钮来定义每个返回参数。可以指定参数的名称、类型、默认值等属性。 7. 在接口定义完成后,可以点击“保存”按钮保存接口。 8. 然后,可以点击“发送请求”按钮发送请求并获取返回结果。在发送请求时,可以填写具体的请求参数值。 9. APIPOST7 工具会根据定义的请求参数和返回参数验证请求的合法性,并在返回结果中展示具体的返回参数值。 10. 可以根据返回结果来判断是否成功获取了正确的返回数据。 通过以上步骤,我们可以使用 APIPOST7 工具来定义和测试 API请求参数和返回参数,从而确保 API 的正常运行。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值