Ответ 1
Если у вас установлен formencode или его можно установить, выйдите из своего variableecode module
Я хотел бы преобразовать POST из Webob MultiDict в вложенный словарь. Например.
Итак, из POST из:
'name=Kyle&phone.number=1234&phone.type=home&phone.number=5678&phone.type=work'
для многоточия;
[('name', 'Kyle'), ('phone.number', '1234'), ('phone.type', 'home'), ('phone.number', '5678'), ('phone.type', 'work')]
во вложенный словарь
{'name': 'Kyle',
'phone': [
{
'number': '12345',
'type': 'home',
},{
'number': '5678',
'type': 'work',
},
Любые идеи?
ИЗМЕНИТЬ
Я закончил извлечение метода variable_decode
из пакета formencode, как опубликовал Уилл.
Единственное изменение, которое требовалось, - сделать списки явными, например.
'name=Kyle&phone-1.number=1234&phone-1.type=home&phone-2.number=5678&phone-2.type=work'
Это лучше по многим причинам.
Если у вас установлен formencode или его можно установить, выйдите из своего variableecode module
У меня не было времени проверить его, и это довольно ограничительно, но, надеюсь, это сработает (я только публикую, потому что прошло некоторое время с тех пор, как вы разместили вопрос):
>>> def toList(s):
... answer = []
... L = s.split("&")
... for i in L:
... answer.append(tuple(i.split('=')))
... return answer
>>> def toDict(L):
... answer = {}
... answer[L[0][0]] = L[0][1]
... for i in L[1:]:
... pk,sk = L[i][0].split('.')
... if pk not in answer:
... answer[pk] = []
... if sk not in answer[pk][-1]:
... answer[pk][sk] = L[i][1]
... else:
... answer[pk].append({sk:L[i][1]})
Если это не 100%, это должно по крайней мере дать вам хорошее начало.
Надеюсь, что это поможет
Я предпочитаю явный способ решить вашу проблему:
Разделите элементы, которые принадлежат к одной и той же структуре (или dict), в одну и ту же группу с таким же именем поля, как
'name=Kyle&phone1=1234&phone1=home&phone2=5678&phone2=work'
Порядок полей в форме гарантирован, поэтому мультидикция будет: ( "имя", "кайл" ), ( "телефон1", "1234", "домашний" ), ( "телефон2", "5678", "работа" ))
Тогда код будет выглядеть следующим образом:
def extract(key, values):
extractor = {
"name":str,
"phone":lambda *args:dict(zip(('number', 'type'), args)
}
trimed_key = re.match(r"^(\w+)", key).group(1)
return trimed_key, extractor(trimed_key, *values)
nested_dict = {}
for i in multidict():
key, values = i[0], i[1:]
nested_dict.setdefault(key, [])
trimed_key, data_wanted = extract(key, values)
nested_dict[trimed_key].append(data_wanted)
for key in nested_dict:
if len(nested_dict[key]) == 1:
nested_dict[key] = nested_dict[key][0]