¿Cómo cambiar un QueryDict de django a Python Dict?

111

Supongamos que tengo el siguiente QueryDict:

<QueryDict: {u'num': [0], u'var1': [u'value1', u'value2'], u'var2': [u'8']}>

Me gustaría tener un diccionario de esto, por ejemplo:

{'num': [0], 'var1':['value1', 'value2'], 'var2':['8']}

(No me importa si el símbolo Unicode upermanece o desaparece).

Si lo hago queryDict.dict(), como sugiere el sitio de django , pierdo los valores adicionales que pertenecen a var1, por ejemplo:

{'num': [0], 'var1':['value2'], 'var2':['8']}

Estaba pensando en hacer esto:

myDict = {}
for key in queryDict.iterkeys():
    myDict[key] = queryDict.getlist(key)

¿Existe una forma mejor?

SaiyanChica
fuente

Respuestas:

103

Esto debería funcionar: myDict = dict(queryDict.iterlists())

Alexandre Vassalotti
fuente
4
queryDict.iterlists () está haciendo un valor de lista de cada clave, ¿tal vez porque espetas listas ?, queryDict.iteritems () si sabes que querydict no contiene list.
panchicore
3
En django 1.6: dict (data._iteritems ())
Bas Koopmans
5
En Django 1.6, dict(queryDict.lists())parece funcionar
Dan Passaro
39
En Django 1.8 en Python 3, todo lo que necesitaba era dict(queryDict).
fmalina
1
Esto no funciona para muchas bibliotecas, incluida la automática. Vea mi pregunta y mi propia respuesta aquí (funciona con v2 y v3 de python): stackoverflow.com/questions/37026535/…
Olivier Pons
193

Nuevo en Django> = 1.4.

QueryDict.dict()

https://docs.djangoproject.com/en/stable/ref/request-response/#django.http.QueryDict.dict

panchicore
fuente
Dos formas de averiguarlo, probarlo o ver la fuente. La respuesta es no: def dict (self): "" "Devuelve el objeto actual como un dict con valores singulares." "" Return dict ((key, self [key]) for key in self)
dalore
6
Si bien esto resuelve el problema para algunas de las personas que visitan esta página desde Google, no responde a la pregunta de OP que pide explícitamente retener múltiples valores para una clave.
disturbios el
1
Gracias a Dios por esta respuesta. Estaba tan despistado
Nic Wanavit
Trabajando en Django 1.11
jobima
16

Esto es lo que terminé usando:

def qdict_to_dict(qdict):
    """Convert a Django QueryDict to a Python dict.

    Single-value fields are put in directly, and for multi-value fields, a list
    of all values is stored at the field's key.

    """
    return {k: v[0] if len(v) == 1 else v for k, v in qdict.lists()}

Según mi uso, esto parece proporcionarle una lista que puede enviar, por ejemplo, un constructor de formularios.

EDITAR: tal vez este no sea el mejor método. Parece que si quieres, por ejemplo, escribir QueryDicten un archivo por alguna loca razón, QueryDict.urlencode()es el camino a seguir. Para reconstruir el QueryDictsimplemente hazlo QueryDict(urlencoded_data).

Dan Passaro
fuente
3
Este método adolece de un comportamiento indeterminado; en una situación en la que una clave determinada puede tener uno o más valores, a veces puede obtener una cadena y, a veces, una lista de cadenas.
Asera
8
from django.utils import six 
post_dict = dict(six.iterlists(request.POST))
ytyng
fuente
6

Si no desea los valores como matrices, puede hacer lo siguiente:

# request = <QueryDict: {u'key': [u'123ABC']}>
dict(zip(request.GET.keys(), request.GET.values()))
{u'key': u"123ABC" }

# Only work for single item lists
# request = <QueryDict: {u'key': [u'123ABC',U 'CDEF']}>
dict(zip(request.GET.keys(), request.GET.values()))
{u'key': u"CDEF" } 

zip es una herramienta poderosa. Lea más sobre ella aquí http://docs.python.org/2/library/functions.html#zip

krichard
fuente
2
Sé que esto tiene casi 6 años, solo señalando para quien llegue a esta respuesta: En Django> = 2.0 (podría funcionar en versiones anteriores también, esa es solo la que estoy usando), puede hacerlo QueryDict.dict()(es decir request.POST.dict()) y devolverá los valores correctamente.
Luca Bezerra
Luca eres una leyenda. ¡Esto me ha estado volviendo loco todo el día! La tuya es la única respuesta que puedo conseguir para trabajar.
scottapotamus
4

Me encontré con un problema similar, queriendo guardar valores arbitrarios de un formulario como valores serializados.

Mi respuesta evita iterar explícitamente el contenido del diccionario: dict(querydict.iterlists())

Para recuperar un valor similar a un diccionario que funciona como el original, se usa una función inversa QueryDict.setlist()para completar un nuevo QueryDictvalor. En este caso, no creo que la iteración explícita sea evitable.

Mis funciones de ayuda se ven así:

from django.http import QueryDict

def querydict_dict(querydict):
    """
    Converts a Django QueryDict value to a regular dictionary, preserving multiple items.
    """
    return dict(querydict.iterlists())

def dict_querydict(dict_):
    """
    Converts a value created by querydict_dict back into a Django QueryDict value.
    """
    q = QueryDict("", mutable=True)
    for k, v in dict_.iteritems():
        q.setlist(k, v)
    q._mutable = False
    return q
Graham Klyne
fuente
3

Actualizar:

myDict = dict(queryDict._iterlists())

Tenga en cuenta: subrayar _en el método iterlists de queryDict. Versión de Django: 1.5.1

Parthyz
fuente
3

dict(request.POST) devuelve un diccionario de Python extraño con valores envueltos en matriz.

{'start': ['2017-01-14T21:00'], 'stop': ['2017-01-14T22:00'], 'email': ['[email protected]']}

donde como {x:request.POST.get(x) for x in request.POST.keys()}devuelve la salida esperada.

{'start': '2017-01-14T21:00', 'stop': '2017-01-14T22:00', 'email': '[email protected]'}
Sandeep
fuente
En Django> = 2.0 (podría funcionar también en versiones anteriores, esa es solo la que estoy usando), puede hacerlo QueryDict.dict()(es decir request.POST.dict()) y devolverá los valores correctamente.
Luca Bezerra
2

simplemente agrega

queryDict=dict(request.GET) o queryDict=dict(QueryDict)

En su vista, los datos se guardarán en querDict como python Dict.

omkar yadav
fuente
1

Así es como resolví ese problema:

dict_ = {k: q.getlist(k) if len(q.getlist(k))>1 else v for k, v in q.items()}
mbijou
fuente
1

Como yo, probablemente esté más familiarizado con los Dict()métodos en Python. Sin embargo, QueryDict()también es un objeto fácil de usar. Por ejemplo, tal vez quisiera obtener el valor de request.GET QueryDict().

Esto se puede hacer de esta manera: request.GET.__getitem__(<key>).

QueryDict()documentación: https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict

Marquistador
fuente
1
Evite el uso de métodos de subrayado doble. La forma más pitónica sería usar request.GET.get(<key>)orequest.GET.getlist(<key>)
Bobort
1

Con Django 2.2pocas soluciones limpias:

  1. QueryDict.dict()es más simple pero se romperá QueryDictcon listas como valores, por ejemplo:
from django.http.request import QueryDict, MultiValueDict

query_dict = QueryDict('', mutable=True)
query_dict.update(MultiValueDict({'a': ['one', 'two']}))
query_dict.update({'b': 'three'})

for key, value in query_dict.dict().items():  # ---> query_dict.dict()
    print(key, value)

saldrá

a two  # <--- missed 'one'
b three
  1. dict(QueryDict) es mejor porque hará un diccionario correcto de listas:
from django.http.request import QueryDict, MultiValueDict

query_dict = QueryDict('', mutable=True)
query_dict.update(MultiValueDict({'a': ['one', 'two']}))
query_dict.update({'b': 'three'})

for key, value in dict(query_dict).items():  # ---> dict(query_dict)
    print(key, value)

saldrá

a ['one', 'two']
b ['three']

cual es correcta.

valex
fuente
0

Probé ambos dict(request.POST)y me request.POST.dict()di cuenta de que si tiene listvalores, por ejemplo, 'var1':['value1', 'value2']anidados en su request.POST, el later ( request.POST.dict()) solo me dio acceso al último elemento en una lista anidada, mientras que el anterior ( dict(request.POST)) me permitió acceder a todos los elementos en una lista anidada.

Espero que esto ayude a alguien.

Codebender
fuente