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?

Antworten:


103

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


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

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).


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

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


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

3

Aktualisieren:

myDict = dict(queryDict._iterlists())

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


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': ['sandeep@sakethtech.com']}

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': 'sandeep@sakethtech.com'}

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.


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

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


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.


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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.