2012-01-30 8 views
10

Me gustaría convertir un POST de Webob MultiDict en un diccionario anidado. P.ej.Cómo convertir un MultiDict a un diccionario anidado

lo tanto, desde un puesto de:

'name=Kyle&phone.number=1234&phone.type=home&phone.number=5678&phone.type=work' 

a un multidict;

[('name', 'Kyle'), ('phone.number', '1234'), ('phone.type', 'home'), ('phone.number', '5678'), ('phone.type', 'work')] 

a un diccionario anidada

{'name': 'Kyle', 
'phone': [ 
    { 
    'number': '12345', 
    'type': 'home', 
    },{ 
    'number': '5678', 
    'type': 'work', 
    }, 

¿Alguna idea?

EDITAR

terminé extraer el método variable_decode del paquete formencode tal como fue anunciado por Will. El único cambio que se requirió es hacer que las listas sean explícitas, por ej.

'name=Kyle&phone-1.number=1234&phone-1.type=home&phone-2.number=5678&phone-2.type=work' 

Cual es mejor por muchas razones.

+0

también echar un vistazo a pimienta de el proyecto Pylons: http://docs.pylonsproject.org/projects/peppercorn/en/latest/ requiere ser más explícito al crear sus formularios, pero permite el anidamiento arbitrario. –

Respuesta

10

Si ha formencode instalado o puede instalarlo, Salida a cabo su variabledecode module

+0

Extraje el método variable_decode() y funciona, perfectamente, gracias. –

1

no he tenido tiempo de probarlo y es bastante restrictiva, pero esperemos que esto va a funcionar (yo sólo dejo porque es pasado un tiempo desde que envió la pregunta):

>>> 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]}) 

Si esto no es 100%, por lo menos debería conseguir que en un buen comienzo.

Esperanza esto ayuda

+0

Gracias por su respuesta, me dio una mejor comprensión de una limitación que había creado al no hacer listas explícitas. Es difícil saber cuándo crear una lista a menos que esté indicado en el nombre de la clave. –

1

prefiero una forma explícita para resolver su problema:

  1. Divida a los miembros que pertenecen a la misma estructura (o dict) en un mismo grupo con el mismo nombre de campo, como

    'name=Kyle&phone1=1234&phone1=home&phone2=5678&phone2=work' 
    
  2. el orden de los campos del formulario está garantizado, por lo que el multidict será: (('nombre', 'Kyle'), ('teléfono1', '123 4' , 'casa'), ('phone2', '5678', 'trabajo'))

  3. continuación, el código será como:

    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] 
    
+0

Gracias por la respuesta. Explícito es la forma de resolver esto. Terminé usando el método variable_decode() del paquete formencode enviado por Will. –

Cuestiones relacionadas