FastAPI 新手入门第 2 篇:让接口接收路径参数和查询参数
2026/6/26 21:21:30 网站建设 项目流程

上一篇我们把服务跑起来了,也在/docs里调用了//ping

这一篇继续往前走一点:让接口从 URL 里接收数据。我会同步更新astapi-beginner-lab项目,大家可以根据tag切换查看每一节课程的代码。

做完后,你会看到浏览器地址栏里的3booktrue,分别变成 Python 函数里的item_idqshort

这次要改哪段代码

这一篇只改app/main.py。先保留上一篇的两个接口,再加一个新的GET /items/{item_id}

这段代码重点看函数参数那一行:item_id来自路径,qshort来自问号后面的查询字符串。

fromfastapiimportFastAPI app=FastAPI()@app.get("/")defread_root():return{"message":"Hello FastAPI"}@app.get("/ping")defping():return{"message":"pong"}@app.get("/items/{item_id}")defread_item(item_id:int,q:str|None=None,short:bool=False):item={"item_id":item_id}ifqisnotNone:item["q"]=qifnotshort:item["description"]="This is a sample item used in the FastAPI beginner series."returnitem

保存后,先不要急着解释概念。我们直接跑起来看结果。

启动服务

进入fastapi-beginner-lab目录,启动虚拟环境,然后运行服务:

.\.venv\Scripts\Activate.ps1$env:PYTHONIOENCODING ="utf-8"$env:PYTHONUTF8 ="1"fastapi dev app/main.py

如果上一篇已经启动过服务,保存文件后它通常会自动重新加载。你也可以停掉后重新运行上面的命令。

打开浏览器访问:

http://127.0.0.1:8000/items/3

应该能看到类似这样的结果:

{"item_id":3,"description":"This is a sample item used in the FastAPI beginner series."}

地址里的3已经进了函数,变成了item_id

路径参数:写在路径里的变量

/items/{item_id}里的{item_id}就是路径参数。

当我们访问:

/items/3

FastAPI 会把路径里的3取出来,传给函数里的item_id

@app.get("/items/{item_id}")defread_item(item_id:int):return{"item_id":item_id}

这里还有一个细节:item_id: int会让 FastAPI 把 URL 里的字符串转成整数。

浏览器地址栏里的内容本来都是字符串。我们写了int以后,函数里拿到的就是整数3,不是字符串"3"

如果访问:

http://127.0.0.1:8000/items/foo

FastAPI 会返回422。响应里会告诉你,错误出现在路径里的item_id

{"loc":["path","item_id"],"msg":"Input should be a valid integer"}

这就是类型标注带来的第一个好处:不合适的数据不会悄悄进入函数。

查询参数:写在问号后面的值

再试一个地址:

http://127.0.0.1:8000/items/3?q=book

这次应该能看到:

{"item_id":3,"q":"book","description":"This is a sample item used in the FastAPI beginner series."}

q=book写在问号后面,这种值叫查询参数。

如果有多个查询参数,用&连接:

http://127.0.0.1:8000/items/3?q=book&short=true

这次返回结果会少一个description

{"item_id":3,"q":"book"}

因为short=true被 FastAPI 转成了 Python 里的True。代码里写了if not short,所以shortTrue时,就不会返回描述字段。

FastAPI 怎么区分这两种参数

这里的判断规则很直观。

如果函数参数名出现在路径里,比如{item_id},它就是路径参数。

@app.get("/items/{item_id}")defread_item(item_id:int):...

如果函数参数名没有出现在路径里,比如qshort,它们就是查询参数。

@app.get("/items/{item_id}")defread_item(item_id:int,q:str|None=None,short:bool=False):...

q: str | None = None表示q可以不传。不传的时候,函数里拿到的是None

short: bool = False表示short也可以不传。不传的时候,默认是False

所以这几个地址都能正常访问:

/items/3 /items/3?q=book /items/3?q=book&short=true

它们调用的是同一个函数,只是传进去的参数不同。

/docs里看参数

打开:

http://127.0.0.1:8000/docs

点开GET /items/{item_id},你会看到页面把参数分成了两类:

  • item_id在 path 里,必须填写。
  • qshort在 query 里,可以不填。

这就是自动文档好用的地方。我们只写了函数参数和类型,FastAPI 就把接口需要什么值展示出来了。

可以在/docs里试三次:

item_id = 3 q 不填 short 不填
item_id = 3 q = book short 不填
item_id = 3 q = book short = true

每次点Execute,看一下请求地址和响应内容怎么变。

项目里通常怎么用

路径参数适合表示“我要操作哪个资源”。

比如:

/items/3 /users/7 /orders/1001

这些地址里的数字通常是资源 ID。

查询参数适合表示“我要怎么查、怎么筛、怎么展示”。

比如:

/items/3?short=true /items?q=book /orders?limit=10

这不是死规则,但对新手很够用。路径里放明确的对象,问号后面放可选条件。

动手改一下

现在给自己留一个小改动:新增一个用户订单接口。

目标是写出这个接口:

GET /users/{user_id}/orders?limit=10

可以先这样写:

@app.get("/users/{user_id}/orders")defread_user_orders(user_id:int,limit:int=10):return{"user_id":user_id,"limit":limit}

然后在/docs里试两个地址:

http://127.0.0.1:8000/users/7/orders?limit=2

你应该能看到:

{"user_id":7,"limit":2}

再试一个故意传错的:

http://127.0.0.1:8000/users/7/orders?limit=abc

如果返回422,并且错误位置指向query里的limit,说明你已经把路径参数、查询参数和类型检查串起来了。

到这里,这一篇的目标就完成了:URL 里的值可以进入 Python 函数,FastAPI 会按类型帮我们转换,也会在传错时返回清楚的错误。

下一篇继续处理另一个常见问题:请求数据不在 URL 里,而是在 JSON 请求体里时,FastAPI 怎么接收和检查。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询