django MultiValueDictKeyError, làm thế nào để tôi đối phó với nó


174

Tôi đang cố lưu một đối tượng vào cơ sở dữ liệu của mình, nhưng nó đang MultiValueDictKeyErrorgây ra lỗi.

Các vấn đề nằm trong biểu mẫu, is_privateđược thể hiện bằng một hộp kiểm. Nếu hộp kiểm KHÔNG được chọn, rõ ràng không có gì được thông qua. Đây là nơi lỗi được cười.

Làm thế nào để tôi đối phó đúng với ngoại lệ này và nắm bắt nó?

Đường dây là

is_private = request.POST['is_private']

1
Một ý tưởng tốt sẽ là cho chúng ta thấy toàn bộ lỗi và dấu vết. Cũng cho chúng tôi thấy nhiều hơn phần mã đó khi lỗi được đưa ra.
rzetterberg

1
Ai đó có thể giải thích tại sao lỗi này xảy ra không? Tôi đã thấy lỗi này khi tôi sử dụng Modelviewset khác nhau trong phần còn lại của django .....
Amrit

1
nó có nghĩa đơn giản: khóa 'is_private' không tồn tại!
ThePhi

Câu trả lời:


281

Sử dụng getphương thức của MultiValueDict . Điều này cũng có mặt trên các tiêu chuẩn và là một cách để tìm nạp một giá trị trong khi cung cấp một mặc định nếu nó không tồn tại.

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

Nói chung là,

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

2
Điều này mang lại cho tôi một giá trị Không nhưng tôi đang gửi giá trị trên POST: /
Jesus Almaral - Hackaprende

Đó là hành vi đúng .. hộp kiểm gửi checkedkhi được chọn nhưng sẽ gửi nullnếu không được chọn. Bạn có thể kiểm tra điều này trong bảng "Mạng" của công cụ Chrome / Firefox DEV. Đó là lý do tại sao bạn đặt Falselàm giá trị mặc định: nếu có null, hãy tạo nó false.
WesternGun

78

Chọn những gì là tốt nhất cho bạn:

1

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

Nếu is_privatekhóa có mặt trong request.POST is_privatebiến sẽ bằng với nó, nếu không, thì nó sẽ bằng Sai.

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
Thực sự không thể đề xuất số 3.
Joe

6
Nó chỉ giống như một sự lạm dụng của hệ thống ngoại lệ. Các ngoại lệ nên được xử lý hành vi đặc biệt (nghĩa là hành vi bạn biết có thể xảy ra và phải xử lý, nhưng bạn không mong đợi trong luồng chương trình bình thường). Trong trường hợp này, ngoại lệ sẽ được ném và bắt trong 50% lưu lượng chương trình có thể. Thêm vào đó là sự chậm lại. Tôi không biết chi tiết về cách thức hoạt động của nó trong Python, nhưng tôi sẽ tưởng tượng ra một dấu vết ngăn xếp đắt tiền sẽ liên quan.
Joe

13
từ django.utils.datastructures nhập MultiValueDictKeyError
Akseli Palén

8
@Joe - Trong Python cách tiếp cận này khá phổ biến. Nếu bạn bắt ngoại lệ, nó sẽ không tự động tạo stacktrace. docs.python.org/2/glossary.html#term-eafp
bjudson

9
Không có gì sai với bước 3. Chúng tôi gọi rằng Dễ dàng hơn để yêu cầu sự tha thứ hơn là sự cho phép (EAFP) và đó là một kiểu mã hóa rất được khuyến nghị trong Python. Rất nhiều bài viết trên StackOverflow thậm chí đã thảo luận về điều này.
Bobort

12

Bạn nhận được điều đó bởi vì bạn đang cố lấy chìa khóa từ điển khi nó không có ở đó. Bạn cần kiểm tra nếu nó ở trong đó trước.

thử:

is_private = 'is_private' in request.POST

hoặc là

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

tùy thuộc vào các giá trị bạn đang sử dụng.


5

Tại sao bạn không thử định nghĩa is_privatetrong các mô hình của mình là default=False?

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

2
Điều đó sẽ không ngăn được lỗi mà anh ta đang kiểm tra POST bằng tay cho giá trị.
Dữ liệu Apollo

4

Một điều cần nhớ là request.POST['keyword']đề cập đến phần tử được xác định bởi namethuộc tính html được chỉ định keyword.

Vì vậy, nếu hình thức của bạn là:

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

sau đó, request.POST['keyword']request.POST['results']sẽ chứa giá trị của các phần tử đầu vào keywordresults, tương ứng.


1

Trước tiên hãy kiểm tra xem đối tượng yêu cầu có tham số khóa 'is_private' không. Hầu hết các trường hợp này là MultiValueDictKeyError xảy ra do thiếu khóa trong đối tượng yêu cầu giống như từ điển. Vì từ điển là một khóa không có thứ tự, nên cặp giá trị bộ nhớ kết hợp của bộ nhớ

Trong một từ khác. request.GET hoặc request.POST là một đối tượng giống như từ điển chứa tất cả các tham số yêu cầu. Điều này là cụ thể cho Django.

Phương thức get () trả về một giá trị cho khóa đã cho nếu khóa nằm trong từ điển. Nếu khóa không có sẵn thì trả về giá trị mặc định Không có.

Bạn có thể xử lý lỗi này bằng cách đặt:

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

1

Đối với tôi, lỗi này xảy ra trong dự án django của tôi vì những điều sau đây:

  1. Tôi đã chèn một siêu liên kết mới trong home.html của tôi trong thư mục mẫu của dự án của tôi như dưới đây:

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

  2. Trong lượt xem, tôi đã có các định nghĩa về đếm và về:

   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. Trong url, tôi có các mẫu url sau:
    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"),
    ]

Như có thể thấy trong không. 3 ở trên, trong mẫu url cuối cùng, tôi đã gọi không chính xác lượt xem.count trong khi tôi cần gọi view.about. Dòng này fulltext = request.GET['fulltext']trong hàm đếm (được gọi nhầm là do nhập sai trong urlpotype) của view.py đã ném ngoại lệ multivaluedictkeykeyor.

Sau đó, tôi đã thay đổi mẫu url cuối cùng trong urls.py thành mẫu chính xác path('about/',views.about,name="about"), và mọi thứ đều hoạt động tốt.

Rõ ràng, nói chung, một lập trình viên mới trong django có thể mắc lỗi tôi đã gọi sai chức năng xem khác cho một url, có thể đang mong đợi bộ tham số khác nhau hoặc chuyển tập hợp các đối tượng khác nhau trong lệnh gọi kết xuất của nó, thay vì hành vi dự định.

Hy vọng điều này sẽ giúp một số lập trình viên mới để django.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.