Errore django MultiValueDictKeyError, come posso gestirlo


174

Sto cercando di salvare un oggetto nel mio database, ma sta generando un MultiValueDictKeyErrorerrore.

Il problema risiede nel modulo, is_privaterappresentato da una casella di controllo. Se la casella di controllo NON è selezionata, ovviamente non viene passato nulla. Questo è dove l'errore viene bloccato.

Come gestisco correttamente questa eccezione e la cattura?

La linea è

is_private = request.POST['is_private']

1
Una buona idea sarebbe di mostrarci l'intero errore e la traccia. Mostraci anche più di quella parte di codice in cui viene generato l'errore.
rzetterberg,

1
Qualcuno può spiegare perché si verifica questo errore? Ho visto questo errore quando uso diversi Modelviewset nel riposo di django .....
Amrit

1
significa semplicemente: la chiave 'is_private' non esiste!
ThePhi,

Risposte:


282

Utilizzare il getmetodo MultiValueDict . Questo è presente anche su dicts standard ed è un modo per recuperare un valore fornendo al contempo un valore predefinito se non esiste.

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

Generalmente,

my_var = dict.get(<key>, <default>)

2
Questo mi dà un valore Nessuno ma sto inviando il valore sul POST: /
Jesus Almaral - Hackaprende,

È il comportamento corretto .. casella di controllo invia checkedquando è selezionata ma invierà nullse non selezionata. Puoi verificarlo nel pannello "Rete" dello strumento Chrome / Firefox DEV. Ecco perché imposti Falsecome valore predefinito: se ottenuto null, fallo false.
WesternGun

78

Scegli ciò che è meglio per te:

1

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

Se la is_privatechiave è presente in request.POST la is_privatevariabile sarà uguale ad essa, in caso contrario, sarà uguale a 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

12
Davvero non posso raccomandare il numero 3.
Joe

6
Sembra solo un abuso del sistema delle eccezioni. Le eccezioni dovrebbero riguardare la gestione di comportamenti eccezionali (vale a dire comportamenti noti che potrebbero verificarsi e che devono essere affrontati, ma che non ci si aspetta dal normale flusso del programma). In questo caso, l'eccezione verrà generata e catturata nel 50% dei possibili flussi di programma. A questo si aggiunge il rallentamento. Non conosco i dettagli di come funziona in Python, ma immagino che sarebbe coinvolto un costoso stack stack.
Joe,

13
da django.utils.datastructures import MultiValueDictKeyError
Akseli Palén

8
@Joe - In Python questo approccio è abbastanza comune. Se riscontri l'eccezione, non genererà automaticamente uno stacktrace. docs.python.org/2/glossary.html#term-eafp
bjudson

9
Non c'è nulla di sbagliato nel passaggio 3. Chiamiamo più facile chiedere perdono che autorizzazione (EAFP), ed è uno stile di codifica altamente raccomandato in Python. Molti post su StackOverflow ne hanno persino discusso.
Bobort,

12

Lo capisci perché stai cercando di ottenere una chiave da un dizionario quando non è lì. Devi testare se è prima lì.

provare:

is_private = 'is_private' in request.POST

o

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

a seconda dei valori che stai utilizzando.


5

Perché non hai provato a definire is_privatenei tuoi modelli come default=False?

class Foo(models.Models):
    is_private = models.BooleanField(default=False)

2
Ciò non impedirebbe l'errore che sta verificando manualmente il POST per il valore.
Apollo Data

4

Un'altra cosa da ricordare è che request.POST['keyword']si riferisce all'elemento identificato dal html specificato nameattributo keyword.

Quindi, se il tuo modulo è:

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

poi, request.POST['keyword']e request.POST['results']conterrà il valore degli elementi di ingresso keyworde results, rispettivamente.


1

Prima controlla se l'oggetto richiesta ha il parametro chiave 'is_private'. Nella maggior parte dei casi questo MultiValueDictKeyError si è verificato per la chiave mancante nell'oggetto richiesta simile a un dizionario. Poiché il dizionario è una chiave non ordinata, la coppia di valori "memorie associative" o "matrici associative"

In un'altra parola. request.GET o request.POST è un oggetto simile a un dizionario contenente tutti i parametri di richiesta. Questo è specifico per Django.

Il metodo get () restituisce un valore per la chiave specificata se la chiave si trova nel dizionario. Se la chiave non è disponibile, restituisce il valore predefinito Nessuno.

È possibile gestire questo errore inserendo:

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

1

Per me, questo errore si è verificato nel mio progetto Django a causa di quanto segue:

  1. Ho inserito un nuovo collegamento ipertestuale nella mia home.html presente nella cartella dei modelli del mio progetto come di seguito:

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

  2. In views.py, avevo le seguenti definizioni di count e 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, avevo i seguenti schemi url:
    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"),
    ]

Come si può vedere nel n. 3 sopra, nell'ultimo schema url, stavo chiamando erroneamente views.count mentre avevo bisogno di chiamare views.about. Questa lineafulltext = request.GET['fulltext'] in count (che è stata erroneamente chiamata a causa di una voce errata in urlpatterns) di views.py ha lanciato l'eccezione keyvalor multivalore.

Quindi ho cambiato l'ultimo pattern url in urls.py con quello corretto, ad es path('about/',views.about,name="about") , , e tutto ha funzionato bene.

Apparentemente, in generale un programmatore principiante in django può commettere l'errore di chiamare erroneamente un'altra funzione di visualizzazione per un url, che potrebbe essere in attesa di un diverso set di parametri o passare diversi set di oggetti nella sua chiamata di rendering, piuttosto che il comportamento previsto.

Spero che questo aiuti alcuni programmatori principianti a django.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.