为什么Tornado将所有请求值转换为列表?即使它不是?
我最近开始使用 tornado
,有一件让我烦恼的事情就是它处理 POST
请求时对数据的解析。
比如在一个示例的 ajax 请求中,如果我发送了名字和邮箱作为表单数据。
服务器上我期望接收到的数据是:
{ "name": "John Doe", "email": "john@doe.me"}
但是它却把每个值都转换成了一个列表,像这样:
{"name": ["John Doe"], "email": ["john@doe.me"]}
有没有人能解释一下为什么 tornado
会这样处理?难道不能直接返回值,而不把它转换成列表吗?
3 个回答
我想这可能是为了让无论值是列表还是其他类型,都能以统一的方式使用,而不需要去检查它们是不是列表。
比如说,假设你想对name
做点什么,但name
有时候是一个列表,有时候是一个单独的值。这样每次处理name
的时候,你都得加上类似下面的代码:
if isinstance(name, list):
# Handle the list
else:
# Handle a string
不过,你可以直接访问name[0]
,而不用担心你会访问到字符串的第一个字符。
免责声明
我不是Tornado的开发者;如果想知道他们为什么采用这种约定,最好还是去问他们。
Tornado支持同一个参数名可以有多个值:
http://example.com/page?foo=1&foo=2
这明显会被解析成:
{'foo': ['1', '2']}
Tornado可以把每个值设置为字符串,如果只有一个值的话;如果有多个值,它会把这些值放在一个字符串列表里。这样的话,你的代码在使用这些值之前就得检查每个值的类型。不过,把所有的值都放在列表里使用会更方便,也更不容易出错。
这不仅仅是关于tornado的事情,这其实是form-urlencoded格式的定义。每个参数可以出现多次,你无法知道一个参数出现一次是想表示一个单独的值,还是想表示一个只有一个元素的列表。为了避免让你去思考这些问题,你在获取请求参数时,应该主要使用RequestHandler.get_argument和RequestHandler.get_arguments这两个方法,这样可以更清楚地知道你是期待一个列表还是一个单独的值。