Error de django MultiValueDictKeyError, ¿cómo lo soluciono?

174

Estoy tratando de guardar un objeto en mi base de datos, pero está arrojando un MultiValueDictKeyErrorerror.

Los problemas se encuentran dentro del formulario, el is_privateestá representado por una casilla de verificación. Si la casilla de verificación NO está seleccionada, obviamente no se pasa nada. Aquí es donde se arroja el error.

¿Cómo trato adecuadamente esta excepción y la atrapo?

La linea es

is_private = request.POST['is_private']
punteado
fuente
1
Una buena idea sería mostrarnos todo el error y la traza. También muéstrenos más de esa porción de código donde se genera el error.
Rzetterberg 05 de
1
¿Alguien puede explicar por qué ocurre este error? He visto este error cuando uso Modelviewset diferente en django rest .....
Amrit
1
significa simplemente: ¡la clave 'is_private' no existe!
ThePhi

Respuestas:

282

Use el getmétodo de MultiValueDict . Esto también está presente en los dictados estándar y es una forma de obtener un valor al tiempo que proporciona un valor predeterminado si no existe.

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

Generalmente,

my_var = dict.get(<key>, <default>)
adamnfish
fuente
2
Esto me da un valor Ninguno pero estoy enviando el valor en la POST: /
Jesus Almaral - Hackaprende
Es el comportamiento correcto ... la casilla de verificación enviar checkedcuando está marcada pero se enviará nullsi no está marcada. Puede verificar esto en el panel "Red" de la herramienta Chrome / Firefox DEV. Es por eso que establece Falseel valor predeterminado: si lo tiene null, hágalo false.
WesternGun
78

Elige lo que es mejor para ti:

1

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

Si la is_privateclave está presente en request.POST, la is_privatevariable será igual a ella; de lo contrario, será igual 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
Luz plateada
fuente
12
Realmente no puedo recomendar el número 3.
Joe
66
Simplemente parece un abuso del sistema de excepción. Las excepciones deben ser para manejar comportamientos excepcionales (es decir, comportamientos que usted sabe que pueden suceder y que debe enfrentar, pero que no espera en el flujo normal del programa). En este caso, la excepción será lanzada y atrapada en el 50% de los posibles flujos del programa. A eso se agrega la desaceleración. No conozco los detalles de cómo funciona en Python, pero me imagino que estaría involucrado un costoso seguimiento de la pila.
Joe
13
from django.utils.datastructures import MultiValueDictKeyError
Akseli Palén
8
@ Joe - En Python este enfoque es bastante común. Si detecta la excepción, no generará automáticamente un seguimiento de pila. docs.python.org/2/glossary.html#term-eafp
bjudson
9
No hay nada de malo en el paso 3. A eso le llamamos más fácil pedir perdón que el permiso (EAFP), y es un estilo de codificación muy recomendable en Python. Muchas publicaciones en StackOverflow incluso han discutido esto.
Bobort
12

Obtiene eso porque está tratando de obtener una clave de un diccionario cuando no está allí. Necesita probar si está allí primero.

tratar:

is_private = 'is_private' in request.POST

o

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

dependiendo de los valores que estés usando.

Joe
fuente
5

¿Por qué no intentaste definir is_privateen tus modelos como default=False?

class Foo(models.Models):
    is_private = models.BooleanField(default=False)
Edson Dota
fuente
2
Eso no evitaría el error que está obteniendo comprobando la POST a mano para el valor.
Apollo Data
4

Otra cosa para recordar es que se request.POST['keyword']refiere al elemento identificado por el nameatributo html especificado keyword.

Entonces, si su formulario es:

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

entonces, request.POST['keyword']y request.POST['results']contendrá el valor de los elementos de entrada keywordy results, respectivamente.

León
fuente
1

Primero verifique si el objeto de solicitud tiene el parámetro clave 'is_private'. La mayoría de los casos de este MultiValueDictKeyError se produjeron por falta de clave en el objeto de solicitud tipo diccionario. Debido a que el diccionario es una clave desordenada, el par de valores "memorias asociativas" o "matrices asociativas"

En otras palabras. request.GET o request.POST es un objeto tipo diccionario que contiene todos los parámetros de solicitud. Esto es específico de Django.

El método get () devuelve un valor para la clave dada si la clave está en el diccionario. Si la clave no está disponible, devuelve el valor predeterminado Ninguno.

Puede manejar este error poniendo:

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

Para mí, este error ocurrió en mi proyecto django debido a lo siguiente:

  1. Inserté un nuevo hipervínculo en mi home.html presente en la carpeta de plantillas de mi proyecto de la siguiente manera:

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

  2. En views.py, tenía las siguientes definiciones de cuenta y sobre:

   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. En urls.py, tenía los siguientes patrones de 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"),
    ]

Como se puede ver en el no. 3 arriba, en el último patrón de URL, estaba llamando incorrectamente views.count mientras que necesitaba llamar a views.about. Esta línea fulltext = request.GET['fulltext']en la función de conteo (que se llamó erróneamente debido a una entrada incorrecta en los patrones de url) de views.py arrojó la excepción multivaluedictkeyerror.

Luego cambié el último patrón de url en urls.py por el correcto path('about/',views.about,name="about"), es decir , y todo funcionó bien.

Aparentemente, en general, un programador novato en django puede cometer el error que cometí al llamar erróneamente a otra función de vista para una url, que podría estar esperando un conjunto diferente de parámetros o pasar un conjunto diferente de objetos en su llamada de representación, en lugar del comportamiento previsto.

Espero que esto ayude a algún programador novato a django.

TNT
fuente