参数在哪里?
参见Http协议,可以知道在Http请求中有如下地方可以存在参数:
- 请求首行的URL中
- 路径参数
- 查询参数
例如:
路径参数示例
在起点中文网中查看不同的小说信息其URL呈现这样的规律:
随着最后一个路径的不同,呈现不同的小说介绍页面
小说1URL:https://book.qidian.com/info/1010868264/
小说2URL:https://book.qidian.com/info/1035010927/
查询参数示例
在百度网中检索不同的关键字时其URL呈现这样的规律:
路径相同而随着检索关键字的不同,URL中?后的key=value中的value值会相应的不同。
检索FastAPI:https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=fastapi
检索Django:https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=django
- 请求体中
这个部分查看的时候无法直接在URL中查看,需要借助浏览器的开发者工具进行查看。查看是通过F12按键,可以打开浏览器的开发者工具。
请求体参数示例
在百度登录界面,当输入不同的用户名和密码后点击登录,其可以跳转到不同的登录界面中。
通过查看"负载"(请求体内容)可以看到对应的请求体的内容。
FastAPI中获取这些参数
路径参数
FastAPI中捕获路径参数主要是通过在路径修饰器和路径操作函数中定义相同的变量名称实现。
在路径装饰器中通过{路径参数变量名}定义路径参数变量的名称。
在路径操作函数中,将相应的路径参数变量作为函数的形参。
无类型路径参数
在无类型路径参数中,FastAPI会将路径参数的类型默认为str类型。
'''
用来演示获取用户输入参数的各种情况
'''
# 第一步:导入FastAPI包
from fastapi import FastAPI
# 第二步:创建FastAPI类的实例对象
app = FastAPI()
# 演示无类型路径参数
# 第三步:创建路径装饰器
@app.get("/item/{item_id}")
# 第四步:定义路径操作函数
async def getItem(item_id):
return {
"item_id":item_id
}
# 第五步:运行服务器
if __name__ == "__main__":
import uvicorn
# 利用uvicorn包的run方法直接运行服务器
# app指定FastAPI类的实例对象
# host指定服务器ip
# port指定端口
uvicorn.run(app=app,host="localhost",port=8080)
示例中1为路径参数,由于没有类型限制,而将整数1当成了字符串1.
有类型路径参数
有类型路径参数就是在定义路径操作函数的时候,设定路径参数的类型。这样FastAPI在解析路径的时候会依据这个类型设定进行类型验证,和类型转换。
# 演示有类型路径参数
@app.get("/items/{page_num}")
async def getItems(page_num:int):
return{
"current_page":page_num,
"items":[1,2,3]
}
在路径操作函数中,针对路径参数进行类型设定。
实例中page_num这个路径参数被设定为整数类型,当路径中传入1时,被转换为整数1。而当传入无法转为整数类型的“one”字符串时,FastAPI输出类型验证错误的报错信息。
有限制路径参数
有限制路径参数就是指针对路径参数进行一些限制,例如限制它的大小或者字符长度,或者进行正则限制。
# 演示有限制路径参数
# fastapi中通过Path函数来对路径参数进行限制
from fastapi import Path
@app.get("/item/large/{item_id}")
async def getLargeItem(item_id:int = Path(gt=100)):
return {"largeItem":item_id}
Path函数形参说明
Path函数通过指定不同的形式参数来限制路径参数,下面针对不同的形式参数进行简单的说明。
参数名称 | 参数说明 |
---|---|
default | 指定默认值,指定了默认值后,该路径参数就成了可选路径参数。当路径中不包含这个路径参数时,FastAPI会以默认值代替。 |
gt | great than表示大于某个浮点数 |
ge | great and equal 表示大于等于某个浮点数 |
lt | less than表示小于某个浮点数 |
le | less and equal表示小于等于某个浮点数 |
min_length | 表示至少有多少个字符长度 |
max_length | 表示最多有多少个字符长度 |
regex | 表示需要满足的正则表达式 |
这里仅针对正则表达式限制进行示例说明:
# 演示正则限制的路径参数
# fastapi中通过Path函数中的regex参数进行正则规则验证限制
@app.get("/{regex_path}")
async def getRegexPath(regex_path:str = Path(regex="^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$")):
return {"right_path":regex_path}
查询参数
当在路径操作函数中声明不属于路径参数的其他参数时,它们自动被解释为“查询参数”。查询参数是键值对的集合,这些键值对位于URL的?之后,并以&符合分隔。
# 演示必填查询参数
# fastapi中当遇到操作路径函数中存在非路径参数的形参时,会将其解释为查询参数
students = [
{"id":"001","name":"Jack","age":19},
{"id":"002","name":"Rose","age":18},
{"id":"003","name":"Tom","age":21},
{"id":"004","name":"Jarry","age":20},
]
@app.get("/student")
async def getStu(name:str,age:int):
stus = []
for stu in students:
if stu["name"] == name and stu["age"] >= age:
stus.append(stu)
return {"students":stus}
必填查询参数
必填查询参数就是在查询参数中没有设定默认值的查询参数。
# 演示必填查询参数
# fastapi中当遇到操作路径函数中存在非路径参数的形参时,会将其解释为查询参数
students = [
{"id":"001","name":"Jack","age":19},
{"id":"002","name":"Rose","age":18},
{"id":"003","name":"Tom","age":21},
{"id":"004","name":"Jarry","age":20},
]
@app.get("/student")
async def getStu(name:str,age:int):
stus = []
for stu in students:
if stu["name"] == name and stu["age"] >= age:
stus.append(stu)
return {"students":stus}
就是一个必填查询参数。当进行请求时如果缺失了一个查询参数会得到一个错误提示信息。
可选查询参数
当查询参数存在默认值的时候,它就会被认为是一个可选的查询参数。当进行请求时如果没有填写可选查询参数,依旧能够得到服务器的正确相应。
# 演示可选查询参数
# fastapi中当查询参数具有默认值的时候,该查询参数就是可选查询参数
# 导入Union类,是为了表示复合类的数据类型
from typing import Union
@app.get("/students")
# Python中语法规则要求可选查询参数必须要在必填查询参数后面出现
async def getStus(age:int,name:Union[str,None]=None):
stus = []
for stu in students:
if name:
if stu['name'] == name and stu['age'] > age:
stus.append(stu)
else:
if stu['age'] > age:
stus.append(stu)
return {"students":stus}
本例中name是可选查询参数,age是必填查询参数
在URL中查询参数的位置可以随意填写而不用和路径操作函数中定义的顺序一致!
有限制查询参数
和有限制路径参数类似,FastAPI中也可以针对查询参数进行一些限制。要实现查询参数的限制,必须要使用Query方法。
# 演示有限制查询参数
# 在fastapi中当想对查询参数进行限制的时候,需要导入Query方法
from fastapi import Query
@app.get("/limit/stus")
async def getStuByName(name:Union[str,None] = Query(default=None,min_length=4)):
for stu in students:
if stu['name'] == name:
return {"student":stu}
Query函数形参说明
参见上面Path函数形参说明。
请求体参数
当你需要将数据从客户端发送给API时,你将其作为请求体发送。
在FastAPI中使用Pydantic模型来声明请求体。请求体是以JSON格式进行读取的。
!要使用请求体发送数据,必须使用:POST, PUT, DELETE 或PATCH方法
请求体参数使用流程
# 演示请求体参数
# 在fastapi中通过Pydantic来声明请求体
# 第一步:导入pydantic包中的BaseModel类
from pydantic import BaseModel
# 第二步:自定义一个继承自BaseModel的类作为请求体的数据模型
class Student(BaseModel):
id:str
name:str
age:int
@app.post('/student')
# 第三步:将自定义的数据模型类作为形参的数据类型
async def addStu(info:Student):
students.append(info)
return {"students":students}
由于post请求无法直接通过浏览器进行验证,这里使用了POSTMAN这个工具,测试这部分内容。
路径参数,查询参数和请求体参数同时出现时如何区分?
- 如果在路径中也声明了该参数,它将被用作路径参数
- 如果参数属于单一类型(int,float,str,bool等),它将被解释为查询参数
- 如果参数的类型被声明为Pydantic模型,它将被解释为请求体
- 如果参数属于单类型单用了Body函数作为默认值,它将被解释为请求体
# 演示多参数类型同时出现的场景
class Item(BaseModel):
name:str
description:Union[str,None] = None
price: float
tax:Union[float,None] = None
@app.put("/items/{item_id}")
# item_id为路径参数
# item为请求体参数
# q为查询参数
async def create_item(item_id:int,item:Item,q:Union[str,None] = None):
# item.dict()将请求体转化为字典
# **将字典进行解引用,指向每个key的真实value
result = {"item_id":item_id, **item.dict()}
if q:
result.update({"q":q})
return result
有限制请求体参数
请求体参数的限制由于其声明请求体参数的方式有多种而不同,详情见下一篇文章。