避免遗漏与重复的游标分页
目标
把排序、过滤、游标和响应投影分开,再通过 FastAPI 请求把它们重新连接起来。
为什么重要
一次正常请求的成功,并不能保证边界值和故障恢复。本实验先把每个函数的契约以小规模实现或测试,再把它们连接到真实运行中。评分不是只看代码是否存在或报告里的措辞,而是检查结果、异常和存储状态。请保留前面步骤的代码,继续进行下一步。
步骤
- 在
/root/work/fa-pagination-lab/service.py中,让 parse_limit(value) 接收字符串形式的整数,在 1–50 范围内时返回 int,其余情况以 ValueError 拒绝。第一步的准备用下面的命令完成。
mkdir -p /root/work/fa-pagination-lab
cp /opt/fixtures/practice_depth/fa-pagination-lab/* /root/work/fa-pagination-lab/
cd /root/work/fa-pagination-lab
- 在
/root/work/fa-pagination-lab/service.py中,让 ordered_rows(rows) 返回按 id 升序排列的新列表。不要修改输入的 rows。每一行都有唯一的正整数 id,以及 name、category、internal_cost。 - 在
/root/work/fa-pagination-lab/service.py中,让 filter_rows(rows, category=None) 在 category 为 None 时返回全部,指定了 category 时只按原顺序返回与之完全相同的类别。不存在的类别返回空列表。 - 在
/root/work/fa-pagination-lab/service.py中,让 encode_cursor(item_id) 把正整数 id 的十进制字符串转换为 UTF-8,然后返回包含 padding 的 URL-safe base64 字符串。 - 在
/root/work/fa-pagination-lab/service.py中,让 decode_cursor(token) 把上述游标还原为正整数。非法的 base64、空值、0、负数以及非数字的值,都是 ValueError。只允许 ASCII 十进制数字,不要忽略换行和垃圾字符。 - 在
/root/work/fa-pagination-lab/service.py中,让 page_after(rows, after, limit) 按升序返回 id > after 的行,最多 limit 条。返回值是 (page, next_cursor),只有存在剩余行时,才对 page 的最后一个 id 编码。空列表和到达末尾时为 None。 - 在
/root/work/fa-pagination-lab/service.py中,让 public_item(row) 返回只包含 id、name、category 的新字典。不要删除或修改原件中的 internal_cost。 - 在
/root/work/fa-pagination-lab/service.py中,让 create_app(rows) 返回一个带有 GET /items 的 FastAPI 应用。limit 默认 10,after 默认无,category 默认无。组合前面的函数,返回 {items: [...], next_cursor: 字符串或 null},对非法的 limit 和 after 以 422 响应。
参考
- 软件包已安装在镜像中。不需要联网,也不需要 pip install。
- 准备用的复制只做一次。再次复制会把工作文件重置。
- 评分器会导入你的 service.py,用不同的 id 和临时存储来运行。不要把结果写成常量。
- 每一步的评分都在 45 秒内运行。不要制造无限循环或真实的等待。
把 limit 的范围固定为契约
在 /root/work/fa-pagination-lab/service.py 中,让 parse_limit(value) 接收字符串形式的整数,在 1–50 范围内时返回 int,其余情况以 ValueError 拒绝。第一步的准备用下面的命令完成。
mkdir -p /root/work/fa-pagination-lab
cp /opt/fixtures/practice_depth/fa-pagination-lab/* /root/work/fa-pagination-lab/
cd /root/work/fa-pagination-lab
不要掩盖 int 转换错误,要在转换之后同时检查下限和上限。
评分可以用 bash /opt/lab/checks/fa-pagination-lab/01-contract.sh 直接复现。保存文件后请重新运行。
把输入顺序和响应顺序分开
在 /root/work/fa-pagination-lab/service.py 中,让 ordered_rows(rows) 返回按 id 升序排列的新列表。不要修改输入的 rows。每一行都有唯一的正整数 id,以及 name、category、internal_cost。
list.sort 会修改原件。请比较一下 sorted 和 key 函数。
评分可以用 bash /opt/lab/checks/fa-pagination-lab/02-contract.sh 直接复现。保存文件后请重新运行。
先应用过滤,再分页
在 /root/work/fa-pagination-lab/service.py 中,让 filter_rows(rows, category=None) 在 category 为 None 时返回全部,指定了 category 时只按原顺序返回与之完全相同的类别。不存在的类别返回空列表。
如果先截取两条再过滤类别,就会出现空页和遗漏。
评分可以用 bash /opt/lab/checks/fa-pagination-lab/03-contract.sh 直接复现。保存文件后请重新运行。
用游标表示最后一个 id
在 /root/work/fa-pagination-lab/service.py 中,让 encode_cursor(item_id) 把正整数 id 的十进制字符串转换为 UTF-8,然后返回包含 padding 的 URL-safe base64 字符串。
base64.urlsafe_b64encode 接收 bytes。返回的 bytes 也要转成字符串。不要把它当作安全令牌来解读。
评分可以用 bash /opt/lab/checks/fa-pagination-lab/04-contract.sh 直接复现。保存文件后请重新运行。
及早拒绝损坏的游标
在 /root/work/fa-pagination-lab/service.py 中,让 decode_cursor(token) 把上述游标还原为正整数。非法的 base64、空值、0、负数以及非数字的值,都是 ValueError。只允许 ASCII 十进制数字,不要忽略换行和垃圾字符。
利用 b64decode 的 altchars 和 validate=True,并在解码之后也检查值的取值域。
评分可以用 bash /opt/lab/checks/fa-pagination-lab/05-contract.sh 直接复现。保存文件后请重新运行。
准确区分最后一页
在 /root/work/fa-pagination-lab/service.py 中,让 page_after(rows, after, limit) 按升序返回 id > after 的行,最多 limit 条。返回值是 (page, next_cursor),只有存在剩余行时,才对 page 的最后一个 id 编码。空列表和到达末尾时为 None。
“拿到了 limit 条”和“存在下一行”是两回事。比较用的是 >,而不是 >=。
评分可以用 bash /opt/lab/checks/fa-pagination-lab/06-contract.sh 直接复现。保存文件后请重新运行。
从响应中去除内部字段
在 /root/work/fa-pagination-lab/service.py 中,让 public_item(row) 返回只包含 id、name、category 的新字典。不要删除或修改原件中的 internal_cost。
与黑名单相比,用白名单来创建新对象,即使以后新增了内部字段,也更安全。
评分可以用 bash /opt/lab/checks/fa-pagination-lab/07-contract.sh 直接复现。保存文件后请重新运行。
合并成真正的 HTTP 契约
在 /root/work/fa-pagination-lab/service.py 中,让 create_app(rows) 返回一个带有 GET /items 的 FastAPI 应用。limit 默认 10,after 默认无,category 默认无。组合前面的函数,返回 {items: [...], next_cursor: 字符串或 null},对非法的 limit 和 after 以 422 响应。
用 TestClient(create_app(rows)) 发起请求。遵守“过滤 → 游标分页 → 公开字段”的顺序,并且只把 ValueError 转换为 HTTP 错误。
评分可以用 bash /opt/lab/checks/fa-pagination-lab/08-contract.sh 直接复现。保存文件后请重新运行。