質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1641閲覧

DjangoのテンプレートタグとJavaScriptを併用して簡単なクイズの正誤判定を行いたい

kensoon

総合スコア48

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/02/19 17:04

前提・実現したいこと

Djangoの練習を行うために、出題された英単語に対し、正しい意味を選択した場合に点数を加算するプログラムを作成しています。JavaScriptをほとんど触ったことがないので、手動で作成したコンテキストをhtml側のテンプレートタグで展開し、そこで判定するためのサンプルを作成している状況です。

問題と回答の紐付けの方法をかんがえ

発生している問題・エラーメッセージ

正しい答えを選択して集計ボタンを押しても、点数が0点から変化しない状態です。

該当のソースコード

python

1views.py 2 3def sample(request): 4 quiz_answer_dict = { 5 'sample': {'例': ['りんご', '取る', '例', '考える']}, 6 'think': {'考える': ['オレンジ', '考える', '取る', 'お茶']}, 7 'listen': {'聞く': ['見る', '泳ぐ', '聞く', '得する']}, 8 'swim': {'泳ぐ': ['りんご', '例', '泳ぐ', 'ノート']}, 9 } 10 11 return render( 12 request, 13 'wordapp/quiz_sample.html', 14 {'quiz_answer_dict': quiz_answer_dict} 15 )

html

1<h3>クイズ</h3> 2{% for question_english, answer_choice_dict in quiz_answer_dict.items %} 3 <div class="quiz"> 4 <p class="question_english">{{ question_english }}</p> 5 {% for answer, choice_list in answer_choice_dict.items %} 6 <p class="answer">answer: {{ answer }}</p> 7 <form name="choice_form"> 8 {% csrf_token %} 9 {% for choice in choice_list %} 10 <input class="choice" type="radio" value="{{ choice }}" name="choice">choice: {{ choice }} 11 {% endfor %} 12 </form> 13 {% endfor %} 14 </div> 15{% endfor %} 16<input type="button" value="集計" onclick="aggregate()"> 17<p>正解した問題数 <span id="number_of_right_answer"></span></p>

javascript

1function aggregate(){ 2 let number_of_right_answer = 0; 3 const quiz_list = document.querySelectorAll("div.quiz"); 4 console.log(quiz_list); 5 /* 6 問題単位のループ 7 */ 8 for (let i = 0; i < quiz_list.length; i++){ 9 const quiz = quiz_list[i]; 10 const answer = quiz.querySelectorAll("p.answer"); 11 const choices = quiz.querySelectorAll("input[name='choice']"); 12 /* 13 選択肢単位のループ 14 */ 15 for (let j = 0; j < choices.length; j++){ 16 if(choices[j].checked){ 17 if(choices[j].value == answer){ 18 number_of_right_answer++; 19 break; 20 } 21 } 22 } 23 } 24 25 document.getElementById("number_of_right_answer").textContent = number_of_right_answer; 26}

試したこと

こちらを参考に、

  • formに名前をつけて、一括して取得してから判定する方法

javascript

1const choice1 = document.form1.value;

の1,2,...と変化していく変数名をfor文とlengthから作成する方法が思いつかなかったので断念しました。

  • inputのname属性の値を利用して、一括して取得して判定する方法

javascript

1const choice = document.getElementsByName("choice1");

問題と回答を紐付ける方法を思いつかなかったので断念しました。

補足情報(FW/ツールのバージョンなど)

python 3.7.9
Django 3.1.6

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Django側から渡しているデータの形があまりよくないような気がします。
また生成されるhtml内の各要素にidがないのでJavaScriptでアクセスしにくいのが原因だと思います。

一例ですが、サンプルコードを書きました。
(POST送信している様子がないのでformタグや{% csrf_token %}は飾りです)

  • views.py

python

1def sample(request): 2 quizzes = [ 3 { 4 'id': 1, 5 'word': 'sample', 6 'answer': '例', 7 'choices': ['りんご', '取る', '例', '考える'] 8 }, 9 { 10 'id': 2, 11 'word': 'think', 12 'answer': '考える', 13 'choices': ['オレンジ', '考える', '取る', 'お茶'] 14 }, 15 { 16 'id': 3, 17 'word': 'listen', 18 'answer': '聞く', 19 'choices': ['見る', '泳ぐ', '聞く', '得する'] 20 }, 21 { 22 'id': 4, 23 'word': 'swim', 24 'answer': '泳ぐ', 25 'choices': ['りんご', '例', '泳ぐ', 'ノート'] 26 } 27 ] 28 29 return render( 30 request, 31 'wordapp/quiz_sample.html', 32 {'quizzes': quizzes} 33 )
  • quiz_sample.html

html

1<h3>クイズ</h3> 2<form> 3 {% csrf_token %} 4 <input type="hidden" id="quiz-length" value="{{ quizzes | length }}"> 5 {% for quiz in quizzes %} 6 <div class="quiz"> 7 <p class="question_english">{{ quiz.word }}</p> 8 <p class="answer">answer: {{ quiz.answer }}</p> 9 <input type="hidden" id="answer-{{ quiz.id }}" value="{{ quiz.answer }}"> 10 {% for choice in quiz.choices %} 11 <input id="choice-{{ quiz.id }}-{{ forloop.counter }}" class="choice" type="radio" value="{{ choice }}" 12 name="quiz-{{ quiz.id }}"> 13 <label for="choice-{{ quiz.id }}-{{ forloop.counter }}">choice: {{ choice }}</label> 14 {% endfor %} 15 </div> 16 {% endfor %} 17 <input type="button" value="集計" onclick="aggregate()"> 18 <p>正解した問題数 <span id="number_of_right_answer"></span></p> 19</form>
  • JavaScript

javascript

1function aggregate() { 2 let result = 0; 3 let quiz_length = document.getElementById('quiz-length').value; 4 // 問題単位のループ 5 for (var i = 1; i <= quiz_length; i++) { 6 var answer = document.getElementById(`answer-${i}`).value; 7 var choices = document.getElementsByName(`quiz-${i}`); 8 // 選択肢単位のループ 9 for (var j = 0; j < choices.length; j++) { 10 if (choices[j].checked) { 11 if (answer == choices[j].value) { 12 result++; 13 break; 14 } 15 } 16 } 17 } 18 document.getElementById("number_of_right_answer").textContent = result; 19}

投稿2021/02/20 17:33

errormaker74

総合スコア230

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kensoon

2021/02/21 02:56

ご対応ありがとうございました。当初想像していた通りに動作させることができました。 errormaker74さんのご指摘の中で、自分が理解できていなかった、知らなかった、考えつかなかった内容が以下になります。 ・コンテキストは辞書で渡されるのが基本であり、チュートリアルのように.値でアクセスできるため、わざわざ直で展開するための辞書を作るのは無駄である ・idを設定することで、getElementByIdにより、階層構造を意識せずに値を取得できる。また、階層構造を利用する際も、極力無駄な階層は減らすべきである ・問題のサイズや答えなど、直接HTMLで表示するものではなくても、そこにhiddenとiidを設定すれば、Script上で利用しやすくなる 以上のように、非常に示唆に富んだ、有り難い回答でした。繰り返しになりますが、本当にご対応ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問