django MultiValueDictKeyError Fehler, wie gehe ich damit um?

174

Ich versuche, ein Objekt in meiner Datenbank zu speichern, aber es wird ein MultiValueDictKeyErrorFehler ausgegeben.

Das Problem liegt im Formular, das is_privatedurch ein Kontrollkästchen dargestellt wird. Wenn das Kontrollkästchen NICHT aktiviert ist, wird offensichtlich nichts übergeben. Hier wird der Fehler behoben.

Wie gehe ich richtig mit dieser Ausnahme um und fange sie ab?

Die Linie ist

is_private = request.POST['is_private']
dotty
quelle
1
Eine gute Idee wäre es, uns den gesamten Fehler und die Spur zu zeigen. Zeigen Sie uns auch mehr von dem Teil des Codes, in dem der Fehler ausgelöst wird.
Rzetterberg
1
Kann jemand erklären, warum dieser Fehler auftritt? Ich habe diesen Fehler gesehen, wenn ich ein anderes Modelviewset in Django Rest verwende .....
Amrit
1
es bedeutet einfach: der Schlüssel 'is_private' existiert nicht!
ThePhi

Antworten:

281

Verwenden Sie die MultiValueDict- getMethode. Dies ist auch in Standarddiktaten vorhanden und bietet eine Möglichkeit, einen Wert abzurufen und gleichzeitig einen Standardwert anzugeben, falls dieser nicht vorhanden ist.

is_private = request.POST.get('is_private', False)

Allgemein,

my_var = dict.get(<key>, <default>)
Adamnfish
quelle
2
Dies gibt mir einen Wert von Keine, aber ich sende den Wert auf dem POST: /
Jesus Almaral - Hackaprende
Es ist das richtige Verhalten. Kontrollkästchen senden, checkedwenn aktiviert, wird gesendet, nullwenn nicht aktiviert. Sie können dies im Bereich "Netzwerk" des Chrome / Firefox DEV-Tools überprüfen. Aus diesem Grund legen Sie Falseden Standardwert fest: Wenn erhalten null, machen Sie es false.
WesternGun
78

Wählen Sie, was für Sie am besten ist:

1

is_private = request.POST.get('is_private', False);

Wenn der is_privateSchlüssel in request.POST vorhanden ist, ist die is_privateVariable gleich, andernfalls ist sie gleich False.

2

if 'is_private' in request.POST:
    is_private = request.POST['is_private']
else:
    is_private = False

3

from django.utils.datastructures import MultiValueDictKeyError
try:
    is_private = request.POST['is_private']
except MultiValueDictKeyError:
    is_private = False
Silbernes Licht
quelle
12
Ich kann Nummer 3 wirklich nicht empfehlen.
Joe
6
Es scheint nur ein Missbrauch des Ausnahmesystems zu sein. Ausnahmen sollten für den Umgang mit außergewöhnlichem Verhalten sein (dh Verhalten, von dem Sie wissen, dass es auftreten kann und das behandelt werden muss, das Sie jedoch im normalen Programmablauf nicht erwarten). In diesem Fall wird die Ausnahme in 50% der möglichen Programmabläufe ausgelöst und abgefangen. Hinzu kommt die Verlangsamung. Ich weiß nicht genau, wie es in Python funktioniert, aber ich würde mir vorstellen, dass es sich um eine teure Stack-Trace handelt.
Joe
13
aus django.utils.datastructures importieren MultiValueDictKeyError
Akseli Palén
8
@ Joe - In Python ist dieser Ansatz ziemlich verbreitet. Wenn Sie die Ausnahme abfangen, wird nicht automatisch ein Stacktrace generiert. docs.python.org/2/glossary.html#term-eafp
bjudson
9
An Schritt 3 ist nichts auszusetzen. Wir nennen es einfacher, um Vergebung zu bitten als um Erlaubnis (EAFP), und es ist ein sehr empfehlenswerter Codierungsstil in Python. Viele Beiträge auf StackOverflow haben dies sogar diskutiert.
Bobort
12

Sie erhalten das, weil Sie versuchen, einen Schlüssel aus einem Wörterbuch zu erhalten, wenn er nicht vorhanden ist. Sie müssen zuerst testen, ob es dort drin ist.

Versuchen:

is_private = 'is_private' in request.POST

oder

is_private = 'is_private' in request.POST and request.POST['is_private']

abhängig von den Werten, die Sie verwenden.

Joe
quelle
5

Warum haben Sie nicht versucht, is_privatein Ihren Modellen als zu definieren default=False?

class Foo(models.Models):
    is_private = models.BooleanField(default=False)
Edson Dota
quelle
2
Das würde den Fehler nicht verhindern, dass er den POST von Hand auf den Wert überprüft.
Apollo Data
4

Eine andere Sache, an die Sie sich erinnern sollten, ist, dass sie request.POST['keyword']sich auf das Element bezieht, das durch das angegebene HTML- nameAttribut identifiziert wird keyword.

Also, wenn Ihr Formular ist:

<form action="/login/" method="POST">
  <input type="text" name="keyword" placeholder="Search query">
  <input type="number" name="results" placeholder="Number of results">
</form>

dann, request.POST['keyword']und request.POST['results']wird den Wert der Eingangselemente enthalten keywordund results, respectively.

Löwe
quelle
1

Überprüfen Sie zunächst, ob das Anforderungsobjekt den Schlüsselparameter 'is_private' hat. In den meisten Fällen trat dieser MultiValueDictKeyError auf, weil ein Schlüssel im wörterbuchartigen Anforderungsobjekt fehlte. Da das Wörterbuch ein ungeordneter Schlüssel ist, wird das Wertepaar "assoziative Speicher" oder "assoziative Arrays" verwendet.

Mit einem anderen Wort. request.GET oder request.POST ist ein wörterbuchähnliches Objekt, das alle Anforderungsparameter enthält. Dies ist spezifisch für Django.

Die Methode get () gibt einen Wert für den angegebenen Schlüssel zurück, wenn sich der Schlüssel im Wörterbuch befindet. Wenn der Schlüssel nicht verfügbar ist, wird der Standardwert None zurückgegeben.

Sie können diesen Fehler behandeln, indem Sie Folgendes eingeben:

is_private = request.POST.get('is_private', False);
Projesh Bhoumik
quelle
1

Bei mir trat dieser Fehler in meinem Django-Projekt aus folgenden Gründen auf:

  1. Ich habe einen neuen Hyperlink in meine home.html eingefügt, der im Vorlagenordner meines Projekts wie folgt vorhanden ist:

    <input type="button" value="About" onclick="location.href='{% url 'about' %}'">

  2. In views.py hatte ich die folgenden Definitionen von count und about:

   def count(request):
           fulltext = request.GET['fulltext']
           wordlist = fulltext.split()
           worddict = {}
           for word in wordlist:
               if word in worddict:
                   worddict[word] += 1
               else:
                   worddict[word] = 1
                   worddict = sorted(worddict.items(), key = operator.itemgetter(1),reverse=True)
           return render(request,'count.html', 'fulltext':fulltext,'count':len(wordlist),'worddict'::worddict})

   def about(request): 
       return render(request,"about.html")
  1. In urls.py hatte ich die folgenden URL-Muster:
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('',views.homepage,name="home"),
        path('eggs',views.eggs),
        path('count/',views.count,name="count"),
        path('about/',views.count,name="about"),
    ]

Wie in Nr. Zu sehen ist. 3 oben, im letzten URL-Muster, habe ich views.count fälschlicherweise aufgerufen, während ich views.about aufrufen musste. Diese Zeile fulltext = request.GET['fulltext']in der Zählfunktion (die fälschlicherweise wegen falscher Eingabe in URL-Mustern aufgerufen wurde) von views.py hat die multivaluedictkeyerror-Ausnahme ausgelöst.

Dann habe ich das letzte URL-Muster in urls.py in das richtige geändert, dh path('about/',views.about,name="about")alles hat gut funktioniert.

Anscheinend kann ein Programmieranfänger in Django im Allgemeinen den Fehler machen, den ich gemacht habe, indem ich fälschlicherweise eine andere Ansichtsfunktion für eine URL aufgerufen habe, die möglicherweise andere Parametersätze erwartet oder andere Objektsätze in ihrem Renderaufruf übergibt, als das beabsichtigte Verhalten.

Hoffe, dies hilft einigen Neulingen Programmierer zu Django.

TNT
quelle