kazuhira123
@kazuhira123

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

DjangoのMultiValueDictKeyErrorに関して

解決したいこと

Djangoの学習をするためにWebアプリを作成しています。
NullBooleanFieldを使ってプルダウンメニューを実装する際にエラーが発生しました。
原因と解決方法を教えていただけると助かります。
(コード内に学習中に記載したコメント残ってます。分かりにくかったら申し訳ないです。)

開発環境

python 3.10.5
Django 3.0.4

発生している問題・エラー

django.utils.datastructures.MultiValueDictKeyError: 'check'

該当するソースコード

forms.py
from django import forms

class HelloForm(forms.Form): #HelloFormクラスにforms.Formクラスを継承
  check = forms.NullBooleanField(label='Check') #プルダウン用のクラスNullBooleanFieldクラスを元にcheckインスタンスを生成
views.py
from tkinter.messagebox import NO
from turtle import pd
from django.shortcuts import render
from django.http import HttpResponse #HttpResponseクラスをimportする
from django.views.generic import TemplateView #TemplateViewクラスを呼び出す
from .forms import HelloForm #forms.pyのHelloFormクラスを呼び出す

class HelloView(TemplateView):
  def __init__(self):
    self.params = {
      'title':'Hello', #テンプレート側で変数として定義した名前をキーとする辞書を作成
      'massage':'your data',
      'result':None,
    }

  def get(self, request): #GETメソッドで値が渡された時の処理
    return render(request, 'hello/index.html', self.params) #レンダリング時にself.paramsを戻り値として返すだけの処理

  def post(self, request): #POSTメソッドで値が渡された時の処理
    chk = request.POST['check']
    self.params['result'] = 'you selected: "' + chk + '"'
    return render(request, 'hello/index.html', self.params)
index.html
{% load static %} <!--静的ファイルをロードする-->
<!doctype html> <!--DOCTYPE宣言と呼ばれる文書タイプがhtmlであることを示す-->
<html lang="ja"> <!--このhtml要素内でしようされる言語は日本語だということ,ブラウザに言語を認識させるイメージ-->
<head>
  <meta charset="utf-8"> <!--メタ要素というページに関する様々な情報を記述する要素、今回はutf-8という文字コードに設定している-->
  <title>{{title}}</title> <!--テンプレートで使用できる変数にtitleを追加-->
  <link rel="stylesheet"
    href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
    crossorigin="anonymous">
</head>
<body class="container">
  <h1 class="display-4 text-primary">{{title}}</h1>
  <p class="h5 mt-4">{{result|safe}}</p>
  <form action="{% url 'index' %}" method="post"> <!--formタグのaction属性にフォームによって送信された情報を処理するプログラムのurlを指定、method属性でhttpメソッドをpostメソッドに指定-->
    {% csrf_token %} <!--CSRF(リクエスト偽造)対策用のトークンを追加、これで「正しくフォームから送信されたアクセスかどうかを判定できる」-->
    <table>
    {{ form.as_p }} <!--呼び出したFormクラスのフィールドをpタグでくくってBootstrapでのデザインを使う-->
    <tr><td></td><td>
      <input type="submit" class="btn btn-primary my-2"  value="click"> <!--inputタグのtype属性をsubmitにすることで送信ボタンを作成、value属性をclickに指定-->
    </td>
    </table>
  </form>
</body>
</html>

自分で試したこと

chk = request.POST['check']の部分で存在しないキーを呼び出している、といったエラーが出ている。
というところまで分かったのですが、特に解決方法が分かりませんでした。
BooleanFieldを用いた同様の処理ではうまくいっていたのですが、何故エラーが出ているのか皆目見当も付かず・・・
長文での質問恐縮ですがよろしくお願いします。

0

2Answer

HelloFormが読み込めてないのではないでしょうか?

views.py
class HelloView(TemplateView):
    def __init__(self):
        self.params = {
            'title':'Hello', 
            'massage':'your data',
            'result':None,
            'form': HelloForm(),
        }

あとは、

views.py
def post(self, request):
    chk = request.POST.get('check')

とかですかねぇ?

1Like

Comments

  1. @kazuhira123

    Questioner

    回答いただきありがとうございます!
    下記の投稿の通り、無事に実装できました。
    (途中でエラー出た後に何回かrunserverコマンド打ち直したら実装できたのが謎でしたが・・・)

    また、辞書型オブジェクトの値を取得するget()メソッド知りませんでした。
    教えていただき感謝です!
    今後とも宜しくお願いします!

こちらの処理で正常に実装できました!
ありがとうございます!

views.py
from tkinter.messagebox import NO
from turtle import pd
from django.shortcuts import render
from django.http import HttpResponse #HttpResponseクラスをimportする
from django.views.generic import TemplateView #TemplateViewクラスを呼び出す
from .forms import HelloForm #forms.pyのHelloFormクラスを呼び出す

class HelloView(TemplateView):
  def __init__(self):
    self.params = {
      'title':'Hello', #テンプレート側で変数として定義した名前をキーとする辞書を作成
      'massage':'your data',
      'result':None,
      'form':HelloForm(),
    }

  def get(self, request): #GETメソッドで値が渡された時の処理
    return render(request, 'hello/index.html', self.params) #レンダリング時にself.paramsを戻り値として返すだけの処理

  def post(self, request): #POSTメソッドで値が渡された時の処理
    chk = request.POST['check']
    self.params['result'] = 'you selected: "' + chk + '"'
    self.params['form'] = HelloForm(request.POST)
    return render(request, 'hello/index.html', self.params)![スクリーンショット 2022-08-01 21.31.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745310/95f06261-b4d8-ffc1-f3c8-10f9f4e5d247.png)

スクリーンショット 2022-08-01 21.31.23.png

0Like

Comments

  1. @kazuhira123

    Questioner

    上記の件、他のフィールの実装時にも同様のエラー発生し、以下の手順を踏むと正常に実装できるというのが何回か確認できました。
    よく分かりませんがひとまずこれで良しとしたいと思います。。。。

    ①MultiValueDictKeyError発生
    request.POSTの値を変数に代入する処理をrequest.POST.getに変更
    ③変数上記変数の値をself.paramsに代入する処理を一旦''で囲う
    ④表示したいコントロールが実装できるのでコントロールを操作し、データの送受信を行う
    ⑤データが送信できているのを確認したタイミングで①と③で修正した処理を元に戻す
    ⑥記述が最初の状態にも関わらず正常に動作する

Your answer might help someone💌