【问题标题】:Sending a form array to Flask将表单数组发送到 Flask
【发布时间】:2014-09-08 15:02:54
【问题描述】:

我有一个包含多个输入的 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 中做到这一点?

【问题讨论】:

    标签: python html flask


    【解决方案1】:

    您正在关注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')

    【讨论】:

    • 如果我的输入是这样的:hello[][some_sub_field] 在发送表单对象数组的表单中?
    • @RocketPingu:您必须再次提取全名。基本上,在发布到 Flask 时不要使用这种格式。
    【解决方案2】:

    我写了一个解析函数,支持多维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&amp;a[][0]=2,可能会让程序员一头雾水。 a=[[1,2]]a[[1],[2]] 太难选择了。

    所以我建议使用 dict 替换列表:

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

    如果你还想发布复杂的数据,我建议你使用application/json

    【讨论】:

      【解决方案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]
      

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

      【讨论】:

        猜你喜欢
        • 2016-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-18
        相关资源
        最近更新 更多