侧边栏壁纸
博主头像
ahao

A student who writes the code of Python and Java.

  • 累计撰写 15 篇文章
  • 累计创建 22 个标签
  • 累计收到 12 条评论

【FastAPI学习】(四)查询参数

ahao
2022-04-25 / 0 评论 / 1 点赞 / 91 阅读 / 5,234 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-25,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

查询参数

一、什么是查询参数

在上一节中,我们了解了路径参数的使用。这一节要学习的查询参数与路径参数非常类似,都是利用请求路径传递参数,即查询参数也是URL的一部分。那它们有什么区别呢?请看代码清单4-1的代码示例。

代码清单4-1
from fastapi import FastAPI
app = FastAPI()

singer_items_db = [{"singer_name": "陈奕迅"}, {"singer_name": "林宥嘉"}, {"singer_name": "家驹"}]

@app.get("/singers/")
def read_singer(skip: int = 0, limit: int = 10):
    return {"data": singer_items_db[skip: skip + limit], "skip": skip, "limit": limit}

当访问http://127.0.0.1:8000/singers/?skip=1&limit=1时,会返回如下结果,在请求的URL中,除了指定了数据接口的访问路径以外,还提供?skip=1&limit=1这一个字符串,它其实是由查询参数组成的查询字符串。

image-20220425163002492

因此我们可以看出,查询字符串是键值对的集合,这些键值对位于 URL 的 之后,并以 & 符号分隔。在上面的URL中,查询参数为skip和limit,它们的值分别为1,1。在上一节的路径参数中提到,FastAPI默认URL中的参数为字符串,由于查询参数也是URL的一部分,因此这里的查询参数的值也是默认为字符串的。所以在代码清单4-1中,我们为查询参数skip和limit声明了数据类型为int型。FastAPI将它们转换为该类型并针对该类型进行校验。

二、查询参数的默认值

由于查询参数不是路径的固定部分,因此它们可以是可选的,并且可以有默认值。在代码清单4-1中,它们具有 skip=0limit=10 的默认值。因此访问http://127.0.0.1:8000/singers/和访问http://127.0.0.1:8000/singers/?skip=0&limit=10是等价的。

image-20220425164323587 image-20220425164313555

并且,当为查询参数设定默认值以后,在请求数据接口是,可以设定查询参数的值,也可以不设定,还可以只设定部分查询参数的值。未设定查询参数值时,该查询参数会使用默认值。例如:http://127.0.0.1:8000/singers/?skip=2 只设定了查询参数skip=2,那么FastAPI读取skip为2,而limit使用了默认值10。

image-20220425164655870

三、可选查询参数

将查询参数的默认值设置为 None ,声明该参数为可选查询参数。即请求该数据接口时,可以选择性地提供该查询参数。例如代码清单4-2,我们定义了一个通过歌手名查询歌手信息地数据接口,该数据接口设定了一个默认值为None的int型可选查询参数age。当我们提供了查询参数age时,该数据接口会返回满足歌手名为singer_name值和年龄为age值的歌手信息;若不指定查询参数age,则只会返回满足路径参数singer_name值的歌手信息。

代码清单4-2
from typing import Optional

singer_items_db = [{"id": 1, "singer_name": "陈奕迅", "age": 40},
                   {"id": 2, "singer_name": "陈奕迅", "age": 35},
                   {"id": 3, "singer_name": "林宥嘉", "age": 40},
                   {"id": 4, "singer_name": "家驹", "age": 31}]

@app.get("/singers/{singer_name}")
def read_singer(singer_name: str, age: Optional[int] = None):
    if age:
        for singer in singer_items_db:
            if singer["singer_name"] == singer_name and singer["age"] == age:
                return {"singer": singer, "age": age}
        return {"message": "The singer is not exist"}
    return {"singer": [singer for singer in singer_items_db if singer["singer_name"]==singer_name]}

未指定查询参数age时,返回了满足歌手名为陈奕迅的所有歌手信息。

image-20220425174230148

指定查询参数age为35时,返回了同时满足歌手名为陈奕迅,年龄为35的歌手信息。

image-20220425174536247

需要注意:FastAPI能够分辨出路径参数和查询参数。例如上面示例中,singer_name为路径参数,而age为查询参数。

四、查询参数类型转换

在代码清单4-2中,我们声明了age的数据类型为int型。除此之外,我们还可以声明查询参数为 bool 类型,它们将被自动转换。代码清单4-3所示的代码示例,声明了一个bool类型的查询参数status,当访问http://127.0.0.1:8000/singers/陈奕迅?age=35&status=1时,返回了歌手信息,并且status为ture。

代码清单4-3
from typing import Optional
singer_items_db = [{"id": 1, "singer_name": "陈奕迅", "age": 40, "status": False},
                   {"id": 2, "singer_name": "陈奕迅", "age": 35, "status": True},
                   {"id": 3, "singer_name": "林宥嘉", "age": 40, "status": True},
                   {"id": 4, "singer_name": "家驹", "age": 31, "status": False}]

@app.get("/singers/{singer_name}")
def read_singer(singer_name: str, age: Optional[int] = None, status: bool = False):
    if not status:
        return {"status": status}
    if age:
        for singer in singer_items_db:
            if singer["singer_name"] == singer_name and singer["age"] == age:
                return {"singer": singer, "age": age, "status": status}
        return {"message": "The singer is not exist", "status": status}
    return {"singer": [singer for singer in singer_items_db if singer["singer_name"]==singer_name]}
image-20220425182812277

当我们访问http://127.0.0.1:8000/singers/陈奕迅?age=35,即不设定查询参数status的值时,则会使用默认值False。

image-20220425183320869

需要注意:

指定查询参数为bool类型后,1,True, true, on, yes 这几个的字母大写被识别为真;0,false,False,off会被识别为假。

即:status=1 、 status=yes、 status=true、status=on、stauts=True 等价。

status=0、status=False、status=false、status=off 等价。

五、必需查询参数

当我们为非路径参数声明了默认值时(目前而言,我们所知道的仅有查询参数),则该参数不是必需的。如果我们不想添加一个特定的值,而只是想使该参数成为可选的,则将默认值设置为 None。但当我们想让一个查询参数成为必需的,不声明任何默认值即可。如代码清单4-4所示,声明了一个类型为int型的必须查询参数id。当我们请求该数据接口时,若未提供该查询参数,则会返回异常,提示未提供该查询参数id。

代码清单4-4
from typing import Optional
singer_items_db = [{"id": 1, "singer_name": "陈奕迅", "age": 40, "status": False},
                   {"id": 2, "singer_name": "陈奕迅", "age": 35, "status": True},
                   {"id": 3, "singer_name": "林宥嘉", "age": 40, "status": True},
                   {"id": 4, "singer_name": "家驹", "age": 31, "status": False}]

@app.get("/singers/{singer_name}")
def read_singer(singer_name: str, id: int, age: Optional[int] = None):
    if age:
        for singer in singer_items_db:
            if singer["singer_name"] == singer_name and singer["age"] == age and singer["id"]==id:
                return {"singer": singer, "age": age, "id": id}
        return {"message": "The singer is not exist"}
    return {"singer": [singer for singer in singer_items_db if singer["singer_name"]==singer_name]}
image-20220425184507682

当提供该查询参数id=2时,则会返回正确的结果。

image-20220425184532876

需要特别注意的一个问题是:当为一个数据接口定义一些查询参数为必需的,一些具有默认值,而某些则完全是可选的。在这种情况下,必须查询参数 需要位于有默认值和可选的查询参数之前,否则会报错。

例如:def read_singer(singer_name: str, status: bool = False, age: Optional[int] = None, id: int) , 必须查询参数id位于有默认值的查询参数status和可选查询参数age之后,此时代码会报错。

正确的定义为:def read_singer(singer_name: str, id: int, status: bool = False, age: Optional[int] = None)

0

评论区