news 2026/7/27 6:46:05

小白python入门 - 41. 路由、路径与查询参数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
小白python入门 - 41. 路由、路径与查询参数

1. 本课定位:是什么、为何重要

上一课服务已经能跑:/health会回 ok,/docs也能点。但真实 API 不会只有探活——书签业务要按资源区分列表、详情、删除,还要支持搜索和分页雏形。如果所有逻辑都堆在一个main.py里用硬编码路径,文件很快膨胀到难维护。

本课把「服务端如何定义 URL 形状」系统化:路径参数标识资源,查询参数负责过滤与限制,状态码表达结果语义,并用APIRouter按资源拆分。数据仍用内存字典(进程重启即消失),为第 42 课 Body、第 44 课落库留接口形状。学完你应能实现书签的读列表、读详情、删除,并分清 404 与 422。

概念一句话
路径参数嵌在 URL 路径里的变量,如/bookmarks/33
查询参数?后面的键值,如?q=python&limit=10
APIRouter把一组路由拆到子模块,再挂到主app
HTTPException主动抛出业务错误(如 404)并返回 JSON detail

为何重要:参数放错位置、状态码乱用,前端与联调会极度痛苦。

对比已学:

已学本课
客户端「拼 URL、读状态码」服务端「定义 URL、返回状态码」
函数参数来自调用方参数可来自 Path / Query
单文件main.py多文件APIRouter
只有/health资源型/bookmarks

2. 本质:从 HTTP 请求里取值

很多人以为「路由就是字符串匹配」。FastAPI 更进一步:根据装饰器上的路径模板 + 函数参数注解,决定如何从请求里取值;类型转换失败时自动 422,不必手写一堆 if。

上一课你返回固定 JSON;这一课 JSON 开始依赖「谁在访问、带了什么参数」。先建立「入参位置」地图:Path、Query、Body(Body 下节),再写代码才不会把过滤条件塞进路径里。

本质:路径模板 + 注解 → 自动解析与校验;业务「找不到」要自己 404。

入参位置例子适合
Path/bookmarks/{id}资源标识,几乎总是必填
Query?q=&limit=过滤、排序、分页,常可选
BodyJSON(第 42 课)创建/更新的结构化数据
GET /bookmarks/3?q=py | | 路径参数 查询参数 bookmark_id=3 q="py"

3. 约束与常见坑

自动校验很爽,但也带来新坑:"abc"变不成int时是 422,不是你业务里的 404。若一律返回 200 再在 body 里写"error",前端分支会写崩。

这一节把约束和坑表列全:命名一致、REST 名词化路径、204 删除、Router 拆分。红线清楚后,综合实践里的 curl 预期才读得懂。

约束:

  1. 路径参数名与函数参数名一致
  2. 注解成int时,"abc"422(校验失败),不是业务 404。
  3. 404表示「类型对了,但资源不存在」——要自己HTTPException
  4. REST 习惯:路径用名词资源,动作用HTTP 方法
  5. 列表过滤优先 Query,保持资源标识路径稳定。

常见坑:

现象正确直觉
用 200 表示「没找到」前端难写分支应用 404
把过滤条件塞进路径/bookmarks/search/python难扩展过滤优先 Query
单文件上百路由难找、易冲突APIRouter+prefix/tags
删除仍返回大 JSON多余可用204无正文
路径参数名与函数名不一致取值错乱/校验怪名字对齐
422 当 404 处理联调互相甩锅先看是类型错还是真没有

4. 路径参数 vs 查询参数(对照表)

两种参数都是「给服务端传值」,但语义不同:路径说「是哪个资源」,查询说「怎么筛选/限制这次查看」。混用会让 URL 地图混乱。

这一节用总表 + 最小代码钉牢,并介绍Queryge/le/description。这些约束会进 OpenAPI,文档页上的限制不是摆设。

路径参数查询参数
形态/items/5/items?limit=5
必填感强(标识资源)常可选
类型转换注解驱动注解 +Query约束
失败转类型失败 422约束失败 422
书签例子/bookmarks/1?q=python&limit=10
fromfastapiimportQuery@router.get("/bookmarks/{bookmark_id}")defget_one(bookmark_id:int):...@router.get("/bookmarks")deflist_all(q:str|None=None,limit:int=Query(10,ge=1,le=100),):...
Query约束含义
ge/le大于等于 / 小于等于
default不传时的默认值
description写入 OpenAPI 文档

小步预期:limit=0limit=9999应 422(若设置了 ge/le)。


5. 状态码按用途归组

客户端阶段你「读」状态码;服务端阶段你「写」状态码。写错语义比写错字段更难查,因为很多客户端按码分支而不是读 detail 字符串。

本课先掌握 200/204/404/422;201 创建成功会在第 42 课 POST 时高频出现。HTTPException是主动表达业务错误的标准方式。

典型场景
成功有体200查询详情/列表
创建成功201POST 新建(第 42 课常用)
成功无体204DELETE 成功
客户端错404资源不存在
校验错422参数类型/范围不合法
fromfastapiimportHTTPExceptionraiseHTTPException(status_code=404,detail="bookmark not found")
修改前修改后
return {"error": "no"}且 200raise HTTPException(404, detail=...)
前端只能猜 body前端可先看 status 再分支

6. 路由组织:APIRouter

单文件 demo 能跑,但书签、用户、上传一多就会「翻文件翻到哭」。APIRouter让你按资源拆模块:统一前缀、文档 tags、主 app 只负责挂载。

这一节建立目录直觉即可:main.py创建 app 并include_routerrouters/bookmarks.py写资源路由。后续课目录会再长,但「按资源拆 router」的习惯从本课开始。

main.py # 创建 app、include_router routers/bookmarks.py # prefix=/bookmarks, tags=["bookmarks"] routers/__init__.py # 使 routers 成为包
API作用
APIRouter(prefix=..., tags=...)统一前缀与文档分组
app.include_router(router)挂载到应用
@router.get("")挂在 prefix 根,如/bookmarks
@router.get("/{id}")详情路径

注意:@router.get("")@router.get("/")在不同版本/配置下对尾斜杠敏感;本课列表用""配合 prefix,curl 时用/bookmarks无尾斜杠即可。


7. REST 直觉(书签资源)

REST 不是教条考试,而是「调用方好猜」的地图:名词做路径,动词做方法。/getBookmarkById这种动词路径能跑,但难扩展、难缓存、难和前端约定。

用书签资源把本课三个接口钉在地图上。写操作 POST/PATCH 留给模型课;本课聚焦读与删,先把 Path/Query/状态码练熟。

方法路径含义
GET/bookmarks列表(可带 q、limit)
GET/bookmarks/{id}详情
DELETE/bookmarks/{id}删除
POST/bookmarks创建(第 42 课)
PATCH/bookmarks/{id}部分更新(第 42 课)
坏路径习惯更好习惯
/getBookmarksGET /bookmarks
/bookmarks/delete/1DELETE /bookmarks/1
/bookmarks/search/pythonGET /bookmarks?q=python

8. 落地场景:内存书签列表

数据放内存字典:实现快、零依赖,但进程重启即消失——这是刻意选择,不是缺陷。第 44 课再换 SQLite,接口形状尽量保持稳定。

场景表帮助你对照「接口行为」写代码,而不是先纠结数据库选型。

接口行为
GET /bookmarks列表;q模糊标题;limit截断
GET /bookmarks/{id}详情或 404
DELETE /bookmarks/{id}删除或 404;成功 204
GET /health探活(主 app)

内存存储直觉:

_DB = { 1: {"id": 1, "title": "...", "url": "..."}, ... }

9. 小步示例:404 与 422 对照

这是本课最重要的体感实验之一。同一条「看起来像详情」的 URL,失败原因不同,状态码不同。分不清就会在联调时浪费整天。

先看表,综合实践里用 curl 亲自打一遍99abc

请求更可能状态码原因
GET /bookmarks/1(存在)200正常
GET /bookmarks/99(不存在)404业务找不到
GET /bookmarks/abc(id 注解 int)422类型校验失败
GET /bookmarks?limit=0(ge=1)422范围校验失败
DELETE /bookmarks/1成功204成功无正文

10. 环境准备

延续 day40 虚拟环境即可;本课多一个routers包。Windows 推荐 Cygwin/WSL 执行 heredoc。

项目要求
Python3.10+
fastapiuvicorn[standard]
目录day41/main.pyday41/routers/bookmarks.py
mkdir-p~/python-lab/src/day41/routerscd~/python-lab/src/day41# 激活 venv 后pipinstall'fastapi>=0.110''uvicorn[standard]>=0.27'

11. 综合实践:完整可运行脚本

一次写入 router、空__init__、main,并启动验证。请完整跑通四类 curl:过滤列表、详情、不存在、删除。422 实验单独再打一次abc

Windows 请用 Cygwin/WSL 执行;PowerShell 可手建同名文件。Uvicorn 占前台时另开终端验证。

mkdir-p~/python-lab/src/day41/routerscd~/python-lab/src/day41cat>routers/bookmarks.py<<'EOF' from fastapi import APIRouter, HTTPException, Query router = APIRouter(prefix="/bookmarks", tags=["bookmarks"]) _DB = { 1: {"id": 1, "title": "FastAPI 文档", "url": "https://fastapi.tiangolo.com"}, 2: {"id": 2, "title": "Python 官网", "url": "https://www.python.org"}, 3: {"id": 3, "title": "Real Python", "url": "https://realpython.com"}, } @router.get("") def list_bookmarks( q: str | None = None, limit: int = Query(default=10, ge=1, le=100), ): items = list(_DB.values()) if q: ql = q.lower() items = [x for x in items if ql in x["title"].lower()] return {"items": items[:limit], "total": len(items)} @router.get("/{bookmark_id}") def get_bookmark(bookmark_id: int): item = _DB.get(bookmark_id) if not item: raise HTTPException(status_code=404, detail="bookmark not found") return item @router.delete("/{bookmark_id}", status_code=204) def delete_bookmark(bookmark_id: int): if bookmark_id not in _DB: raise HTTPException(status_code=404, detail="bookmark not found") del _DB[bookmark_id] return None EOFcat>routers/__init__.py<<'EOF' EOF cat > main.py << 'EOF' from fastapi import FastAPI from routers import bookmarks app = FastAPI(title="Day41 Bookmark API", version="0.1.0") app.include_router(bookmarks.router) @app.get("/health") def health(): return {"status": "ok"} EOFuvicorn main:app--reload--host127.0.0.1--port8000

验证命令(另开终端):

curl-s"http://127.0.0.1:8000/bookmarks?q=python"curl-s"http://127.0.0.1:8000/bookmarks/1"curl-s"http://127.0.0.1:8000/bookmarks/99"curl-s-o/dev/null-w"%{http_code}\n"-XDELETE"http://127.0.0.1:8000/bookmarks/2"curl-s"http://127.0.0.1:8000/bookmarks/abc"curl-s"http://127.0.0.1:8000/bookmarks?limit=0"

预期要点:

请求预期
q=python标题含 python 的项(大小写不敏感)
id=1200 + 对象
id=99404 +{"detail":"..."}
DELETE 2 成功204
id=abc422
limit=0422

修改前:单文件只有/health
修改后:资源路由拆分,列表可过滤,详情/删除语义完整。


12. 路由注册顺序直觉(了解)

固定路径与动态路径混用时,声明顺序偶尔影响匹配(例如/bookmarks/special/bookmarks/{id})。本课数据简单,但要知道:更具体的路径通常应先于宽泛的{id}

入门不强制踩坑演示;项目变大时若「明明写了路由却 422/404」,回来查顺序与前缀。

建议原因
先写静态子路径避免被{id}吃掉
prefix 统一在 Router减少手写重复/bookmarks
tags 按资源/docs分组清晰

13. 常见问答

集中处理:total 是过滤前还是过滤后、204 有没有 body、内存删除刷新后为何又回来、Query 默认值会不会进 URL。

Q:total应该是过滤后长度还是全库长度?
A:本课示例用过滤后的len(items);产品里要文档写清,前后端对齐即可。

Q:204 响应可以带 JSON 吗?
A:语义上成功无正文;客户端不要依赖 204 的 body。

Q:删除后重启服务数据又在?
A:内存初始_DB写在代码里,重启会重建;第 44 课落库后才持久。

Q:不传limit会怎样?
A:使用默认 10(本课 Query default)。


14. 自我检查清单

勾完再进第 42 课。Path/Query/404/422/Router 五项是本课硬指标。

  • 能解释路径参数与查询参数分工
  • 会写Query(..., ge=, le=)
  • HTTPException(404)
  • 知道abc→422、不存在 id→404
  • APIRouter+include_router
  • DELETE 成功返回 204
  • 跑通过滤列表 curl

15. 与前后课衔接

关系
40会起服务 → 本课定义资源 URL
42本课读删 → 下课 POST/PATCH Body
44内存_DB→ SQLite 表

总结

收束几句带走:路径标识资源,查询负责过滤分页;404 与 422 分工明确;Router 按资源拆分;内存库只为练接口形状。后面加 Body 和数据库时,尽量少改 URL 地图。

  • 路径参数标识资源;查询参数做过滤/分页。
  • 类型/范围失败 → 422;资源不存在 → 404。
  • DELETE 成功常用 204;列表过滤优先 Query。
  • APIRouter(prefix, tags)+include_router拆分维护。
  • 内存字典重启即失,接口形状为后续落库铺路。
  • REST:名词路径 + HTTP 方法,少用动词路径。

小练笔

先做再看答案。可选实践建议真的 curl 一遍 422,把状态码记在本子上。

题 1

/bookmarks/foobookmark_id: int,更常见?

A. 200 B. 404 C. 422

题 2

Query(10, ge=1, le=100)ge含义?

题 3

列表过滤用路径还是查询参数更合适?为什么?

题 4

DELETE 成功为何常用 204?

题 5

写出「获取 id=3 的书签」的方法 + 路径示例。

题 6

判断:业务上找不到 id=99,应返回 422。

题 7

APIRouter(prefix="/bookmarks")后,列表函数装饰@router.get(""),完整路径是?

题 8

limit=1000le=100时更可能?

A. 截断到 100 B. 422 C. 500

题 9(可选实践)

把默认limit改成 2,不传 q 时列表最多几条?动手验证。

题 10

为什么不建议/doDeleteBookmark?id=1这种路径?


小练笔参考答案

先自测再对照。意思对即可。

题 1

C

题 2

greater or equal,最小值 1。

题 3

查询参数;过滤可选、可组合,路径应保持资源标识稳定。

题 4

成功且无需返回正文时,204 语义更贴切。

题 5

GET /bookmarks/3(主机端口按本地环境)。

题 6

(应 404)

题 7

/bookmarks(或等价无尾斜杠形式,按你框架配置)

题 8

B

题 9

最多 2 条(以你修改后运行为准)。

题 10

应用 HTTP 方法表达动作,路径保持资源名词,更易缓存与约定。(合理即可)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/27 6:37:58

n8n工作流蓝绿发布与灰度上线实战指南

1. n8n工作流发布策略的挑战与机遇在自动化工作流管理领域&#xff0c;n8n作为一款开源工具已经获得了大量企业的青睐。我最近在帮一家电商客户部署营销自动化系统时&#xff0c;遇到了一个典型问题&#xff1a;当他们需要更新一个处理每日10万订单的工作流时&#xff0c;直接全…

作者头像 李华
网站建设 2026/7/27 6:33:19

深入OMAP5910 I2C控制器:从协议原理到寄存器级编程实践

1. 项目概述与I2C总线核心价值在嵌入式系统开发中&#xff0c;设备间的通信是构建复杂功能的基石。面对GPIO数量有限、布线复杂度高的挑战&#xff0c;一种名为I2C&#xff08;Inter-Integrated Circuit&#xff09;的串行通信协议脱颖而出&#xff0c;成为了连接微控制器与各类…

作者头像 李华
网站建设 2026/7/27 6:29:40

细胞产业浪潮下健康管理的新趋势

细胞产业浪潮下健康管理的新趋势随着生命科学技术的不断发展&#xff0c;大健康领域迎来了全新的发展机遇&#xff0c;细胞生物技术与健康管理领域的融合&#xff0c;也成为行业关注的方向之一。近年来&#xff0c;国家层面将生物医药相关领域列为重点支持方向&#xff0c;不少…

作者头像 李华
网站建设 2026/7/27 6:27:35

Matlab实现电力系统潮流计算与不对称短路分析

1. 电力系统潮流计算与不对称短路分析概述 电力系统潮流计算和不对称短路分析是电力工程领域的两项基础性工作。前者用于确定系统在稳态运行时的电压、功率分布等关键参数&#xff0c;后者则用于评估系统在故障状态下的电气量变化。这两项工作对于电网规划、运行和保护都具有重…

作者头像 李华
网站建设 2026/7/27 6:27:12

全链路流量分析与性能优化实战

1. 项目背景与核心目标去年第三季度&#xff0c;我们团队接手了一个棘手的线上业务问题&#xff1a;某核心业务系统在流量高峰期频繁出现响应延迟&#xff0c;但常规监控指标&#xff08;CPU、内存、磁盘IO&#xff09;均显示正常。经过两周的无效排查后&#xff0c;我们决定实…

作者头像 李华