10.5. 摄像头的控制 API¶
拥有者需要从任何地方设置运动检测器的灵敏度——刮风的日子里,风会让树木晃动得更厉害。这意味着需要一些路由,让仪表盘能从中读取当前设置,并向其提交更改。
在模块上放一个小小的共享状态字典就足以保存这些旋钮设置。后面的页面会向其中添加更多键;现在只有一个:
state = {
'threshold': 12,
'frame_count': 0,
'trigger_count': 0,
}
10.5.1. 用 GET 读取,用 POST 写入¶
一对路由——一个 get、一个 post——让仪表盘对 state 拥有读/写访问权限:
from microdot import abort
@app.get('/config')
async def get_config(request):
return state
@app.post('/config')
async def set_config(request):
body = request.json
if not body or 'threshold' not in body:
abort(400, 'missing threshold')
try:
threshold = int(body['threshold'])
except (TypeError, ValueError):
abort(400, 'threshold must be an integer')
if not 0 <= threshold <= 100:
abort(400, 'threshold out of range')
state['threshold'] = threshold
return {'ok': True, 'threshold': threshold}
microdot.Request.json 会返回解析为 JSON 的请求主体,如果 Content-Type 不是 application/json 则返回 None。post 处理函数会逐一检查每种失败模式——缺少键、类型错误、超出范围——并通过 microdot.abort() 退出,后者会抛出 microdot.HTTPException,用给定的状态码和消息使处理函数短路。
10.5.2. GET、POST、PUT、DELETE¶
get() 和 post() 是我们用得最多的两个。put() 和 delete() 用于遵循 REST 约定的场景——用 PUT /events/42 替换事件 42,用 DELETE /events/42 删除它。处理函数在其他方面是相同的。
10.5.3. 读取查询字符串和表单¶
仪表盘提交的是 JSON,所以 request.json 正是我们想要的。摄像头还有另外两种接收数据的方式:
args——查询字符串。?foo=1&bar=2会变成一个microdot.MultiDict,你可以用request.args.get('foo')来读取它。form——一个以application/x-www-form-urlencoded提交的 HTML 表单。同样是MultiDict类型。
MultiDict 与字典类似,但允许一个键携带多个值(?tag=cat&tag=dog 就是两个 tag 值);完整接口请参阅 microdot.MultiDict。
10.5.4. 动态 URL 段¶
路由路径可以声明带类型的占位符,microdot 会把它们作为额外参数传给处理函数:
@app.get('/events/<int:event_id>')
async def get_event(request, event_id):
return {'id': event_id, 'msg': 'placeholder'}
支持的转换器有:<int:>、用于自定义正则表达式的 <re:>、用于可包含斜杠的段的 <path:>,以及默认(无前缀)的“匹配直到下一个斜杠之前的任意内容”。<int:event_id> 接受 /events/42 而拒绝 /events/abc——被拒绝的请求会变成一个 404,处理函数不会运行。
10.5.5. 自定义错误响应¶
microdot 默认发送的 404 是纯文本 Not found。仪表盘期望每个响应都是 JSON;请重写 404 处理函数,让它也返回 JSON:
@app.errorhandler(404)
async def not_found(request):
return {'error': 'not found', 'path': request.path}, 404
errorhandler() 既可以接受一个状态码(捕获该状态的每一个错误),也可以接受一个异常类(捕获每一个抛出该异常的处理函数)。(body, status) 元组会使响应短路,而无需构造一个 Response。
现在摄像头对外暴露了它的状态,并接受编辑。