Umgang mit request.GET mit mehreren Variablen für denselben Parameter in Django

81

In einer Django-Ansicht können Sie auf die zugreifen request.GET['variablename'], sodass Sie in Ihrer Ansicht Folgendes tun können:

myvar = request.GET['myvar']

Der tatsächliche request.GET['myvar']Objekttyp ist:

<class 'django.http.QueryDict'>

Wenn Sie nun mehrere Variablen mit demselben Parameternamen übergeben möchten, z.

http://example.com/blah/?myvar=123&myvar=567

Sie möchten, dass eine Python listfür den Parameter zurückgegeben wird myvar, und gehen dann folgendermaßen vor:

for var in request.GET['myvar']:
    print(var)

Wenn Sie jedoch versuchen, nur den letzten in der URL übergebenen Wert zu erhalten, dh im obigen Beispiel, erhalten Sie 567 , und das Ergebnis in der Shell lautet:

5
6
7

Wenn Sie jedoch einen Ausdruck request.GETdavon erstellen, scheint dies listFolgendes zu haben:

<QueryDict: {u'myvar': [u'123', u'567']}>

Ok Update: Es wurde entwickelt, um den letzten Wert zurückzugeben. Mein Anwendungsfall ist, dass ich eine Liste benötige.

von django docs:

QueryDict. getitem (Schlüssel) Gibt den Wert für den angegebenen Schlüssel zurück. Wenn der Schlüssel mehr als einen Wert hat, gibt getitem () den letzten Wert zurück. Löst django.utils.datastructures.MultiValueDictKeyError aus, wenn der Schlüssel nicht vorhanden ist. (Dies ist eine Unterklasse von Pythons Standard-KeyError, sodass Sie sich an das Abfangen von KeyError halten können

QueryDict.getlist (Schlüssel) Gibt die Daten mit dem angeforderten Schlüssel als Python-Liste zurück. Gibt eine leere Liste zurück, wenn der Schlüssel nicht vorhanden ist. Es wird garantiert eine Liste zurückgegeben.

Update: Wenn jemand weiß, warum Django-Entwickler dies getan haben, lassen Sie es mich bitte wissen. Es scheint nicht intuitiv zu sein, eine Liste anzuzeigen, und sie verhält sich nicht wie eine. Nicht sehr pythonisch!

ismail
quelle
4
Ich denke, die Argumentation ist, dass Sie wissen sollten, ob Sie eine Liste oder einen individuellen Wert erwarten. QueryDict.getitem sollte manchmal keine Liste zurückgeben, manchmal ein einzelnes Element - dann müsste jeder immer seinen Rückgabetyp überprüfen, um richtig damit umzugehen.
jgiles

Antworten:

179

Sie möchten die Funktion getlist () des GET-Objekts:

request.GET.getlist('myvar')
AndrewF
quelle
10
Möglicherweise müssen Sie am Ende des Variablennamens ein "[]" hinzufügen, wenn Sie jquery verwenden, um Elemente zurückzusenden.
Danny Staple
2
Ich wusste von getlist, aber das "[]" warf mich. Außerdem habe ich einen Freund namens Andy Staple, und für eine Sekunde dachte ich, er wüsste viel mehr über Django, als mir klar wurde. Das warf mich auch.
Kungphu
1
Dies muss überall auf den Django-Dokumenten, den Django Rest Framework-Dokumenten und rückwärts auf meiner Stirn angebracht werden. Das hat mich wirklich überrascht
Anthony Manning-Franklin
Es scheint, als hätte Django den Ball auf diesen fallen lassen, nicht sicher, ob er beabsichtigt ist
NaturalBornCamper
1

Eine andere Lösung besteht darin, eine Kopie des Anforderungsobjekts zu erstellen ... Normalerweise können Sie ein request.GET- oder request.POST-Objekt nicht durchlaufen, aber Sie können folgende Vorgänge für die Kopie ausführen:

res_set = request.GET.copy()
for item in res_set['myvar']:
    item
...
Gefallener Engel
quelle
2
bist du sicher? Dies ändert für mich überhaupt nichts am Verhalten des QueryDict. Ich bekomme gerade ein weiteres QueryDict mit der gleichen "Einschränkung"
Nuts