(三)表单字段与 JSON 数据
1. GET 表单把具名字段组成查询串
先只做读取:用下拉框选择已读状态。下面的 HTML 文件放在 samples 中,登录后提交就会打开对应 API 地址。
<!-- 项目文件:samples/filter_form.html -->
<!-- GET把具名字段放进查询串,只筛选列表,不新增记录。 -->
<!doctype html><html lang="zh-CN"><meta charset="utf-8"><title>筛选已读状态</title>
<form method="get" action="http://127.0.0.1:8767/api/books">
<label>阅读状态
<select name="finished">
<option value="all">全部</option>
<option value="0">未读</option>
<option value="1">已读</option>
</select>
</label>
<button type="submit">查看记录</button>
</form></html>form 的 method 指定 GET,action 指定目标地址。select 的 name 决定字段名,选项的 value 决定提交值;选择未读后得到 ?finished=0。label 给控件提供说明,button 的 submit 类型触发表单提交。
书架的新增表单使用 POST,把字段编码进请求体。输入框的 name 仍然决定字段名;没有 name 的控件不会以这个字段提交。未勾选的复选框通常不提交那一项,因此服务器要把“缺少已读勾选”转换为 False。
2. 编码形式决定解析过程
# 项目文件:demos/urls_forms.py
# URL中的查询和请求体分别编码;parse_qs保留同名字段的多值结构。
import json
from urllib.parse import parse_qs, urlencode, urlsplit
url = urlsplit("http://127.0.0.1:8767/api/books?finished=0")
print("地址", url.scheme, url.netloc, url.path, parse_qs(url.query))
encoded = urlencode({"title": "Python Web", "tags": "Python,网络"})
print("表单编码", encoded)
print("恢复字段", parse_qs(encoded))
raw = json.dumps(
{"title": "Python Web", "finished": False, "tags": ["网络"]}, ensure_ascii=False
)
print("JSON类型", type(json.loads(raw)["finished"]).__name__)urlsplit 分开协议、主机与端口、路径和查询串;parse_qs 将查询串或表单正文读成“字段名对应值列表”。值是列表,因为同一个名称可以出现多次,本章的单值字段会另外核对次数。
urlencode 处理空格、中文和分隔符。Python Web 中的空格可编码为加号,中文与逗号通过百分号编码保存;解析后恢复字段文本。application/x-www-form-urlencoded 指明这种表单格式。
JSON 的 false 则在解析后成为 Python 的 False,数组成为 list。Content-Type: application/json 告诉服务器采用 JSON 解析;把请求体里的文本改得像 JSON,却仍声明表单类型,不会自动切换解析方式。