将表单数组发送到Flask

时间:2014-07-17 16:15:48

标签: python html flask

我有一个HTML表单,其中包含多个输入,如下所示:

<input name="hello[]" type="text" />
<input name="hello[]" type="text" />
<input name="hello[]" type="text" />

PHP 中,您可以将其作为数组获得,但在使用Flask的情况下,它是否与Python相同?

我试过这个:

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 个答案:

答案 0 :(得分:75)

您正在关注PHP convention of adding brackets to the field names。它不是一个Web标准,但因为PHP支持它开箱即用,它很受欢迎; Ruby on Rails也使用它。

如果您确实使用该约定,要在Flask端获取POST数据,您需要在字段名称中包含方括号。您可以使用MultiDict.getlist()

检索列表的所有
hello = request.form.getlist('hello[]')

当然,您根本不必使用[]惯例。不将[]附加到hello名称将完全正常,此时您将在Flask中使用request.form.getlist('hello')

答案 1 :(得分:1)

我编写了一个支持多维dict的解析函数: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]]太难以选择。

所以我建议用dict替换list:

<input name="hello[0]" type="text" />
<input name="hello[1]" type="text" />

如果您仍想发布复杂数据,建议您使用application/json

答案 2 :(得分:0)

我有一个表单,该表单具有一个或两个级别的数组,所以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]

因此它遍历表单键/值并匹配键中的3组:首先是“基本”名称,然后是两个级别的名称。如果存在第一级或第二级名称,它将创建一个字典,并用发布的值填充它,然后继续删除原始键/值。