django MultiValueDictKeyError error, bagaimana cara menghadapinya

174

Saya mencoba untuk menyimpan objek ke database saya, tetapi ada MultiValueDictKeyErrorkesalahan.

Masalahnya terletak di dalam formulir, is_privatediwakili oleh kotak centang. Jika kotak centang TIDAK dipilih, jelas tidak ada yang berlalu. Di sinilah kesalahan dibuang.

Bagaimana cara saya menangani pengecualian ini dengan benar, dan menangkapnya?

Garisnya adalah

is_private = request.POST['is_private']
Dotty
sumber
1
Ide yang bagus adalah menunjukkan kepada kita seluruh kesalahan dan jejaknya. Juga tunjukkan kami lebih banyak bagian kode di mana kesalahan muncul.
rzetterberg
1
Adakah yang bisa menjelaskan mengapa kesalahan ini terjadi? Saya telah melihat kesalahan ini ketika saya menggunakan Modelviewset yang berbeda dalam istirahat Django .....
Amrit
1
artinya sederhana: kunci 'is_private' tidak ada!
ThePhi

Jawaban:

282

Gunakan metode MultiValueDict get. Ini juga ada pada dicts standar dan merupakan cara untuk mengambil nilai sambil memberikan default jika tidak ada.

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

Umumnya,

my_var = dict.get(<key>, <default>)
Adamnfish
sumber
2
Ini memberi saya nilai Tidak ada tetapi saya mengirim nilai pada POST: /
Jesus Almaral - Hackaprende
Itu adalah perilaku yang benar .. centang kotak kirim checkedketika dicentang tetapi akan dikirim nulljika tidak dicentang. Anda dapat memeriksa ini di panel "Jaringan" alat Chrome / Firefox DEV. Itu sebabnya Anda menetapkan Falsesebagai nilai default: jika didapat null, buatlah false.
WesternGun
78

Pilih yang terbaik untuk Anda:

1

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

Jika is_privatekunci ada di request.POST is_privatevariabel akan sama dengan itu, jika tidak, maka itu akan sama dengan 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
Cahaya Perak
sumber
12
Benar-benar tidak dapat merekomendasikan nomor 3.
Joe
6
Sepertinya penyalahgunaan sistem pengecualian. Pengecualian harus untuk menangani perilaku luar biasa (yaitu perilaku yang Anda tahu itu mungkin terjadi, dan harus berurusan dengan, tetapi Anda tidak mengharapkannya dalam aliran program normal). Dalam hal ini, pengecualian akan dibuang dan ditangkap 50% dari kemungkinan aliran program. Ditambah dengan itu adalah perlambatan. Saya tidak tahu detail cara kerjanya di Python, tapi saya akan membayangkan stack-trace yang mahal akan terlibat.
Joe
13
dari django.utils.datastructures import MultiValueDictKeyError
Akseli Palén
8
@ Jo - Di Python pendekatan ini sangat umum. Jika Anda menangkap pengecualian, itu tidak akan secara otomatis menghasilkan stacktrace. docs.python.org/2/glossary.html#term-eafp
bjudson
9
Tidak ada yang salah dengan langkah 3. Kami menyebutnya lebih mudah untuk meminta pengampunan daripada izin (EAFP), dan itu adalah gaya pengkodean yang sangat disarankan dalam Python. Banyak posting di StackOverflow bahkan telah membahas hal ini.
Bobort
12

Anda mendapatkannya karena Anda mencoba untuk mendapatkan kunci dari kamus ketika itu tidak ada. Anda perlu menguji apakah ada di sana terlebih dahulu.

mencoba:

is_private = 'is_private' in request.POST

atau

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

tergantung pada nilai yang Anda gunakan.

Joe
sumber
5

Mengapa Anda tidak mencoba mendefinisikan is_privatedalam model Anda sebagai default=False?

class Foo(models.Models):
    is_private = models.BooleanField(default=False)
Edson Dota
sumber
2
Itu tidak akan mencegah kesalahan dia mendapatkan memeriksa POST dengan tangan untuk nilainya.
Apollo Data
4

Hal lain yang perlu diingat adalah yang request.POST['keyword']mengacu pada elemen yang diidentifikasi oleh nameatribut html yang ditentukan keyword.

Jadi, jika formulir Anda adalah:

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

kemudian, request.POST['keyword']dan request.POST['results']akan berisi nilai elemen input keyworddan results, masing-masing.

Leo
sumber
1

Pertama periksa apakah objek permintaan memiliki parameter kunci 'is_private'. Sebagian besar kasus, MultiValueDictKeyError ini terjadi karena kunci yang hilang di objek permintaan seperti kamus. Karena kamus adalah kunci yang tidak berurutan, nilai pasangan "memori asosiatif" atau "array asosiatif"

Dengan kata lain. request.GET atau request.POST adalah objek seperti kamus yang berisi semua parameter permintaan. Ini khusus untuk Django.

Metode get () mengembalikan nilai untuk kunci yang diberikan jika kunci ada di kamus. Jika kunci tidak tersedia maka mengembalikan nilai default Tidak ada.

Anda dapat menangani kesalahan ini dengan meletakkan:

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

Bagi saya, kesalahan ini terjadi pada proyek Django saya karena hal berikut:

  1. Saya memasukkan hyperlink baru ke home.html saya yang ada di folder template proyek saya seperti di bawah ini:

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

  2. Di views.py, saya memiliki definisi hitung dan sekitar sebagai berikut:

   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. Di urls.py, saya memiliki pola url berikut:
    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"),
    ]

Seperti yang bisa dilihat pada no. 3 di atas, dalam pola url terakhir, saya salah memanggil views.count sedangkan saya perlu memanggil views.about. Baris ini fulltext = request.GET['fulltext']dalam fungsi hitung (yang secara keliru disebut karena entri yang salah dalam urlpatterns) dari views.py melemparkan pengecualian multivaluedictkeyerror.

Lalu saya mengubah pola url terakhir di urls.py ke yang benar yaitu path('about/',views.about,name="about"), dan semuanya bekerja dengan baik.

Rupanya, secara umum programmer pemula di Django dapat membuat kesalahan yang saya buat dengan salah memanggil fungsi tampilan lain untuk url, yang mungkin mengharapkan set parameter yang berbeda atau melewati set objek yang berbeda dalam panggilan rendernya, daripada perilaku yang dimaksud.

Semoga ini bisa membantu beberapa programmer pemula untuk Django.

TNT
sumber