Wie ändere ich ein Django QueryDict in Python Dict?

110

Stellen wir uns vor, ich hätte das folgende QueryDict:

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

Ich hätte gerne ein Wörterbuch daraus, zB:

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

(Es ist mir egal, ob das Unicode-Symbol ubleibt oder geht.)

Wenn ich dies tue queryDict.dict(), wie von der Django-Site vorgeschlagen , verliere ich die zusätzlichen Werte, die dazu gehören var1, z.

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

Ich dachte darüber nach:

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

Gibt es einen besseren Weg?

SaiyanGirl
quelle

Antworten:

103

Das sollte funktionieren: myDict = dict(queryDict.iterlists())

Alexandre Vassalotti
quelle
4
queryDict.iterlists () erstellt aus jedem Schlüssel einen Listenwert, möglicherweise weil Sie Spektrenlisten haben?, queryDict.iteritems (), wenn Sie wissen, dass querydict keine Liste enthält.
Panchicore
3
In Django 1.6: dict (data._iteritems ())
Bas Koopmans
5
In Django 1.6 dict(queryDict.lists())scheint zu funktionieren
Dan Passaro
38
In Django 1.8 auf Python 3 brauchte ich nur dict(queryDict).
Fmalina
1
Dies funktioniert nicht für viele Bibliotheken, einschließlich authomatic. Siehe meine Frage und meine eigene Antwort hier (funktioniert mit v2 und v3 von Python): stackoverflow.com/questions/37026535/…
Olivier Pons
193

Neu in Django> = 1.4.

QueryDict.dict()

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

Panchicore
quelle
Zwei Möglichkeiten, dies herauszufinden, auszuprobieren oder die Quelle anzuzeigen. Die Antwort lautet nein: def dict (self): "" Gibt das aktuelle Objekt als Diktat mit singulären Werten zurück. "" Return dict ((key, self [key]) für key in self)
dalore
6
Dies löst zwar das Problem für einige der Personen, die von Google auf diese Seite kommen, beantwortet jedoch nicht die Frage von OP, in der explizit die Beibehaltung mehrerer Werte für einen Schlüssel gefordert wird.
Aufruhr
1
Gott sei Dank für diese Antwort. Ich war so ahnungslos
Nic Wanavit
Arbeiten an Django 1.11
jobima
16

Folgendes habe ich letztendlich verwendet:

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

Aus meiner Verwendung scheint dies eine Liste zu erhalten, die Sie beispielsweise an einen Formularkonstruktor zurücksenden können.

EDIT: Vielleicht ist dies nicht die beste Methode. Es scheint, wenn Sie zB QueryDictaus irgendeinem verrückten Grund in eine Datei schreiben möchten , QueryDict.urlencode()ist dies der richtige Weg. Um das zu rekonstruieren, QueryDictmachst du es einfach QueryDict(urlencoded_data).

Dan Passaro
quelle
3
Diese Methode leidet unter unbestimmtem Verhalten; In einer Situation, in der ein bestimmter Schlüssel einen oder mehrere Werte haben kann, erhalten Sie manchmal eine Zeichenfolge und manchmal eine Liste von Zeichenfolgen.
Asherah
8
from django.utils import six 
post_dict = dict(six.iterlists(request.POST))
ytyng
quelle
6

Wenn Sie die Werte nicht als Arrays verwenden möchten, können Sie Folgendes tun:

# 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 ist ein leistungsstarkes Tool. Weitere Informationen finden Sie hier http://docs.python.org/2/library/functions.html#zip

krichard
quelle
2
Ich weiß, dass dies fast 6 Jahre alt ist, und weise nur darauf hin, wer diese Antwort erreicht: In Django> = 2.0 (funktioniert möglicherweise auch in älteren Versionen, das ist nur die, die ich verwende), können Sie dies tun QueryDict.dict()(dh request.POST.dict()) und es gibt die Werte korrekt zurück.
Luca Bezerra
Luca du bist eine Legende. Das hat mich den ganzen Tag verrückt gemacht! Ihre Antwort ist die einzige, die ich zur Arbeit bringen kann.
Scottapotamus
4

Ich stieß auf ein ähnliches Problem und wollte beliebige Werte aus einem Formular als serialisierte Werte speichern.

Meine Antwort vermeidet es, den Wörterbuchinhalt explizit zu wiederholen: dict(querydict.iterlists())

Um einen wörterbuchähnlichen Wert abzurufen, der als Original fungiert, wird mit einer Umkehrfunktion QueryDict.setlist()ein neuer QueryDictWert aufgefüllt. In diesem Fall halte ich die explizite Iteration nicht für vermeidbar.

Meine Hilfsfunktionen sehen folgendermaßen aus:

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
quelle
3

Aktualisieren:

myDict = dict(queryDict._iterlists())

Bitte beachten Sie: Unterstreichen Sie _in der Iterlists-Methode von queryDict. Django-Version: 1.5.1

Parthyz
quelle
3

dict(request.POST) Gibt ein seltsames Python-Wörterbuch mit Array-umschlossenen Werten zurück.

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

Dabei wird die {x:request.POST.get(x) for x in request.POST.keys()}erwartete Ausgabe zurückgegeben.

{'start': '2017-01-14T21:00', 'stop': '2017-01-14T22:00', 'email': '[email protected]'}
Sandeep
quelle
In Django> = 2.0 (funktioniert möglicherweise auch in älteren Versionen, das ist nur die, die ich verwende) können Sie dies tun QueryDict.dict()(dh request.POST.dict()) und die Werte werden ordnungsgemäß zurückgegeben.
Luca Bezerra
2

einfach hinzufügen

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

Aus Ihrer Sicht werden Daten in querDict als Python Dict gespeichert.

Omkar Yadav
quelle
1

So habe ich dieses Problem gelöst:

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

Wie ich sind Sie wahrscheinlich besser mit Dict()Methoden in Python vertraut . Das QueryDict()Objekt ist jedoch auch einfach zu bedienen. Zum Beispiel wollten Sie vielleicht den Wert von der erhaltenrequest.GET QueryDict() .

Sie können dies folgendermaßen tun : request.GET.__getitem__(<key>).

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

Marquistador
quelle
1
Vermeiden Sie die Verwendung von Methoden mit doppeltem Unterstrich. Der pythonischere Weg wäre, request.GET.get(<key>)oderrequest.GET.getlist(<key>)
Bobort
1

Mit Django 2.2gibt es nur wenige saubere Lösungen:

  1. QueryDict.dict()ist am einfachsten, aber es wird QueryDictmit Listen als Werte gebrochen , zB:
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)

wird ausgegeben

a two  # <--- missed 'one'
b three
  1. dict(QueryDict) ist besser, weil es das richtige Wörterbuch der Listen macht:
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)

wird ausgegeben

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

welches ist richtig.

Valex
quelle
0

Ich habe versucht , aus beide dict(request.POST)und request.POST.dict()und erkennen , dass , wenn Sie listWerte zum Beispiel 'var1':['value1', 'value2']in Ihrem verschachtelt request.POST, die später ( request.POST.dict()) nur gab ich in einer verschachtelten Liste zum letzten Elemente zugreifen , während der ehemaligen (dict(request.POST) ) mich erlaubt , alle Elemente in einer verschachtelten Liste zuzugreifen.

Ich hoffe das hilft jemandem.

Codebender
quelle