Comment changer un django QueryDict en Python Dict?


111

Supposons que j'ai le QueryDict suivant:

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

J'aimerais avoir un dictionnaire à partir de ceci, par exemple:

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

(Peu m'importe si le symbole Unicode ureste ou disparaît.)

Si je le fais queryDict.dict(), comme suggéré par le site django , je perds les valeurs supplémentaires appartenant à var1, par exemple:

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

Je pensais faire ceci:

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

Y a-t-il un meilleur moyen?

Réponses:


103

Cela devrait fonctionner: myDict = dict(queryDict.iterlists())


4
queryDict.iterlists () crée une valeur de liste à partir de chaque clé, peut-être parce que vous affichez des listes ?, queryDict.iteritems () si vous savez que querydict ne contient pas de liste.
panchicore

3
Dans django 1.6: dict (data._iteritems ())
Bas Koopmans

5
Dans Django 1.6, dict(queryDict.lists())semble fonctionner
Dan Passaro

39
Dans Django 1.8 sur Python 3, tout ce dont j'avais besoin était dict(queryDict).
fmalina

1
Cela ne fonctionne pas pour de nombreuses bibliothèques, y compris authomatic. Voir ma question et ma propre réponse ici (fonctionne avec les v2 et v3 de python): stackoverflow.com/questions/37026535/…
Olivier Pons

194

Deux façons de le découvrir, de l'essayer ou d'afficher la source. La réponse est non: def dict (self): "" "Renvoie l'objet actuel sous forme de dict avec des valeurs singulières." "" Return dict ((key, self [key]) for key in self)
dalore

6
Bien que cela résout le problème pour certaines personnes qui accèdent à cette page à partir de Google, cela ne répond pas à la question de OP qui demande explicitement de conserver plusieurs valeurs pour une clé.
émeute le

1
Merci mon Dieu pour cette réponse. J'étais tellement
ignorant

Travailler sur Django 1.11
Jobima

16

C'est ce que j'ai fini par utiliser:

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

D'après mon utilisation, cela semble vous donner une liste que vous pouvez renvoyer par exemple à un constructeur de formulaire.

EDIT: ce n'est peut-être pas la meilleure méthode. Il semble que si vous voulez par exemple écrire QueryDictdans un fichier pour une raison folle, QueryDict.urlencode()c'est la voie à suivre. Pour reconstruire le QueryDictvous faites simplement QueryDict(urlencoded_data).


3
Cette méthode souffre d'un comportement indéterminé; dans une situation où une clé donnée peut avoir une ou plusieurs valeurs, vous pouvez parfois obtenir une chaîne, et parfois une liste de chaînes.
Asherah

8
from django.utils import six 
post_dict = dict(six.iterlists(request.POST))

6

Si vous ne souhaitez pas que les valeurs sous forme de tableaux, vous pouvez effectuer les opérations suivantes:

# 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 est un outil puissant pour en savoir plus ici http://docs.python.org/2/library/functions.html#zip


2
Je sais que cela a presque 6 ans, soulignant simplement pour quiconque atteint cette réponse: dans Django> = 2.0 (peut également fonctionner dans les anciennes versions, c'est juste celle que j'utilise), vous pouvez le faire QueryDict.dict()(c'est-à-dire request.POST.dict()) et cela renverra les valeurs correctement.
Luca Bezerra

Luca tu es une légende. Cela m'a rendu fou toute la journée! La vôtre est la seule réponse que je puisse trouver au travail.
scottapotamus

4

J'ai rencontré un problème similaire, souhaitant enregistrer des valeurs arbitraires d'un formulaire en tant que valeurs sérialisées.

Ma réponse évite d'itérer explicitement le contenu du dictionnaire: dict(querydict.iterlists())

Afin de récupérer une valeur de type dictionnaire qui fonctionne comme l'original, une fonction inverse utilise QueryDict.setlist()pour remplir une nouvelle QueryDictvaleur. Dans ce cas, je ne pense pas que l'itération explicite soit évitable.

Mes fonctions d'assistance ressemblent à ceci:

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

3

Mettre à jour:

myDict = dict(queryDict._iterlists())

Remarque: soulignement _dans la méthode iterlists de queryDict. Version de Django: 1.5.1


3

dict(request.POST) renvoie un dictionnaire python étrange avec des valeurs enveloppées dans un tableau.

{'start': ['2017-01-14T21:00'], 'stop': ['2017-01-14T22:00'], 'email': ['sandeep@sakethtech.com']}

où as {x:request.POST.get(x) for x in request.POST.keys()}renvoie la sortie attendue.

{'start': '2017-01-14T21:00', 'stop': '2017-01-14T22:00', 'email': 'sandeep@sakethtech.com'}

Dans Django> = 2.0 (peut également fonctionner dans les anciennes versions, c'est juste celui que j'utilise), vous pouvez le faire QueryDict.dict()(c'est-à-dire request.POST.dict()) et il retournera les valeurs correctement.
Luca Bezerra

2

ajoutez simplement

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

Dans votre vue et les données seront enregistrées dans querDict en tant que python Dict.


1

Voici comment j'ai résolu ce problème:

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

1

Comme moi, vous êtes probablement plus familier avec les Dict()méthodes en python. Cependant, le QueryDict()est également un objet facile à utiliser. Par exemple, vous souhaitiez peut-être obtenir la valeur du fichier request.GET QueryDict().

Vous pouvez le faire comme ceci: request.GET.__getitem__(<key>).

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


1
Évitez d'utiliser les méthodes de double soulignement. La manière la plus pythonique serait d'utiliser request.GET.get(<key>)ourequest.GET.getlist(<key>)
Bobort

1

Avec Django 2.2il existe peu de solutions propres:

  1. QueryDict.dict()est le plus simple mais il cassera QueryDictavec des listes comme valeurs, par exemple:
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)

sortira

a two  # <--- missed 'one'
b three
  1. dict(QueryDict) est mieux car il fera un dictionnaire correct des listes:
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)

sortira

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

qui est correct.


0

J'ai essayé les deux dict(request.POST)et request.POST.dict()et j'ai réalisé que si vous aviez des listvaleurs par exemple 'var1':['value1', 'value2']imbriquées dans votre request.POST, le later ( request.POST.dict()) ne me donnait accès qu'au dernier élément d'une liste imbriquée tandis que l'ancien ( dict(request.POST)) me permettait d'accéder à tous les éléments d'une liste imbriquée.

J'espère que ça aidera quelqu'un.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.