将表单数组发送到Flask
我有一个HTML表单,里面有多个输入框,名字是这样的:
<input name="hello[]" type="text" />
<input name="hello[]" type="text" />
<input name="hello[]" type="text" />
在PHP中,你可以把这些输入框的值当作一个数组来处理,但在Python中,用Flask框架处理时也是这样吗?
我试过这样做:
hello = request.form['hello']
print(hello)
但是没有成功,我收到了一个400 Bad Request
的错误:
Bad Request
The browser (or proxy) sent a request that this server could not understand.
那我该怎么在Flask中实现呢?
3 个回答
我有一个表单,里面有一维或二维的数组,也就是说可能是 a[1]
或者 b[1][2]
。
我写了一个正则表达式的解决方案,用来把这些数据放进字典里。
import re
re_post = re.compile(r'([a-z_]*)(\[(.*?)\])?(\[(.*?)\])?')
for post_key, post_value in request.form.copy().items():
matches = list(re_post.findall(post_key)[0][0::2])
if matches[1]:
request.form.setdefault(matches[0], {})
if matches[2]:
request.form[matches[0]].setdefault(matches[1], {})
request.form[matches[0]][matches[1]][matches[2]] = post_value
else:
request.form[matches[0]][matches[1]] = post_value
else:
continue
del request.form[post_key]
这个方案会遍历表单中的每个键和值,并在键中匹配三个部分:首先是“基础”名称,然后是两个层级的名称。如果第一个层级或第二个层级的名称存在,它就会创建一个字典,并用提交的值填充这个字典,然后再把原来的键值对删除。
我写了一个解析函数,可以处理多维字典:php_post=parse_multi_form(request.form)
def parse_multi_form(form):
data = {}
for url_k in form:
v = form[url_k]
ks = []
while url_k:
if '[' in url_k:
k, r = url_k.split('[', 1)
ks.append(k)
if r[0] == ']':
ks.append('')
url_k = r.replace(']', '', 1)
else:
ks.append(url_k)
break
sub_data = data
for i, k in enumerate(ks):
if k.isdigit():
k = int(k)
if i+1 < len(ks):
if not isinstance(sub_data, dict):
break
if k in sub_data:
sub_data = sub_data[k]
else:
sub_data[k] = {}
sub_data = sub_data[k]
else:
if isinstance(sub_data, dict):
sub_data[k] = v
return data
使用方法:
>>> request.form={"a[0][name]": "ahui", "a[0][sex]": "female", "a[1][name]": "bhui", "a[1][sex]": "male"}
>>> parse_multi_form(request.form)
{'a': {0: {'name': 'ahui', 'sex': 'female'}, 1: {'name': 'bhui', 'sex': 'male'}}}
警告:这个函数不支持列表,比如
a[][0]=1&a[][0]=2
,这可能会让程序员感到困惑。选择a=[[1,2]]
或者a[[1],[2]]
都太难了。
所以我建议用字典来替代列表:
<input name="hello[0]" type="text" />
<input name="hello[1]" type="text" />
如果你还是想发送复杂的数据,我建议使用 application/json
你正在遵循一种在PHP中常见的做法,就是在字段名称后面加上方括号。这虽然不是一个网络标准,但因为PHP本身就支持这种写法,所以它变得很流行;Ruby on Rails也使用了这种方式。
如果你选择使用这种方式,那么在Flask中获取POST数据时,你需要在字段名称中包含方括号。你可以使用MultiDict.getlist()
来获取这个列表的所有值:
hello = request.form.getlist('hello[]')
当然,你完全可以不使用[]
这种方式。如果不在hello
这个名称后面加上[]
,也是完全可以的,这时你可以在Flask中使用request.form.getlist('hello')
来获取数据。