请求表单 - urlencoded数据

时间:2014-10-08 21:20:47

标签: python python-requests

更新:

我认为我现在更接近了,如果将我的数据结构更改为以下内容并使用:

urllib.urlencode(data, doseq=True)

data ={'Properties': [('key', 'KeyLength'), ('value', '512')], 'Category': 'keysets', 'Offset': '0', 'Limit': '10'}

我现在得到的内容更接近,但仍然不太正确:

Category=keysets&Limit=10&Properties=('key', 'KeyLength')&Properties=('value', '512')&Offset=0

我正在重写这个问题,因为我觉得我知道问题所在,但仍然不知道如何修复它。

我认为问题涉及我需要发送的表单数据包含具有相同名称的表单字段这一事实。即属性'。这是我的数据结构:

data = {'Properties': [{'key': 'KeyLength', 'value': '512'}], 'Category': 'keysets', 'Offset': '0', 'Limit': '100'}

这就是Web服务收到它时的显示方式:

Form Data:
  Properties[0][key]:KeyLength
  Properties[0][value]:768
  Category:
  Offset:0
  Limit:100

我发布了使用'请求'这样:

req = requests.post('http://server1/ws1/api/data/filters/', data=data)

然而它似乎最终会像这样:

Category=keysets&Limit=100&Properties=('key', 'KeyLength')&Offset=0

而不是这样:

Properties[0][key]=KeyLength&Properties[0][value]=768&Category=&Offset=0&Limit=100

有人可以告诉我我做错了什么。

2 个答案:

答案 0 :(得分:2)

你无法直接获得。从Python标准库手册中,Python url编码以这样的方式工作:转换映射对象或一系列双元素元组

不支持您想要的爆炸列表或哈希值:您必须预处理数据。你可以尝试这样的功能:

def transform(h, resul = None, kk=None):
    if resul is None:
        resul = {}
    for (k, v) in h.items():
        key = k if kk is None else "%s[%s]" % (kk, k)
        if isinstance(v, list) or isinstance(v, tuple):
            for i, v1 in enumerate(v):
                transform(v1, resul, '%s[%d]' % (key, i))
        elif isinstance(v, dict):
            for i, v1 in v.items:
                transform(v1, resul, '%s[%s]' % (key, i))
        else:
            resul[key] = v
    return resul

使用原始数据结构,它给出:

>>> data = {'Properties': [{'key': 'KeyLength', 'value': '512'}], 'Category': 'keysets', 'Offset': '0', 'Limit': '100'}
>>> transform(data)
{'Category': 'keysets', 'Limit': '100', 'Properties[0][key]': 'KeyLength', 'Offset': '0', 'Properties[0][value]': '512'}

然后根据您的要求对其进行编码

答案 1 :(得分:0)

看起来,Serge提供的答案对于嵌入在树中的列表不会很好。 (他们没有items()方法)

以下是对我有用的想法的变体:

def flattenForPost(h, resul = None, kk=None):

  if resul is None:
    resul = {}

  if isinstance(h, str) or isinstance(h, bool):
    resul[kk] = h
  elif isinstance(h, list) or isinstance(h, tuple):
    for i, v1 in enumerate(h):
        flattenForPost(v1, resul, '%s[%d]' % (kk, i))
  elif isinstance(h, dict):
    for (k, v) in h.items():
        key = k if kk is None else "%s[%s]" % (kk, k)
        if isinstance(v, dict):
            for i, v1 in v.items():
                flattenForPost(v1, resul, '%s[%s]' % (key, i))
        else:
            flattenForPost(v, resul, key)
  return resul