Django
前回、足し算テストアプリの準備をして、2ページの移動をする方法を解説しました。
今回は足し算テストアプリ作成の基礎編として、作成した2ページ間で値を受け渡しする方法を試していきます。
これまでにもフォームを使って、入力した値をプログラムに渡し、処理をして結果を表示するということはやってきたのですが、「フォームに入力された値ではない値」に関しては受け渡しをしたことがありませんでした。
私自身が足し算テストアプリを作っている時にここで結構苦労したので、多くの人に参考になるんじゃないかなと思います。
今回、修正するファイルは以下の4つです。
- /webapp/tashizan1/forms.py
- /webapp/tashizan1/views.py
- /webapp/tashizan1/templates/tashizan1/index.html
- /webapp/tashizan1/templates/tashizan1/answercheck.html
webapp
├── ...
└── tashizan1
├── __init__.py
├── admin.py
├── apps.py
├── forms.py <- これ
├── migrations
│ └── __init__.py
├── models.py
├── templates
│ └── tashizan1
│ ├── answercheck.html <- これ
│ └── index.html <- これ
├── tests.py
├── urls.py
└── views.py <- これ
まずは足し算テストアプリの流れを解説します。
足し算テストアプリの流れ
今回作成する足し算アプリですが、このような流れで動くようプログラムしていきます。
- index.htmlが表示されたら、問題がランダムな数字を使って表示される
- 解答欄に答えを入力し、「答え合わせ」ボタンを押す
- answercheck.htmlに移動し、答え合わせをした結果を表示する
- 再度テストする場合は「もう一回!」ボタンを押し、index.htmlを再度表示する
- index.htmlでは再度ランダムな数字を使って問題が作成される
ここで鍵となることは「問題がランダムな数字を使って表示」されることです。
つまりindex.htmlが表示された際、randomモジュールを使って、ランダムな数字を2つ取得し、それを表示します。
そして解答が入力され、「答え合わせボタン」をクリックした際、そのランダムな数字をanswercheck.htmlに受け渡します。
受け渡されたランダムな2つの数字を使って、足し算し、入力された値と比較し、正解か不正解かを判断します。
この場合、フォームに入力される値は「解答」だけす。
そしてランダムな2つの数字は単に表示され、answercheck.htmlに受け渡されなければなりません。
そのような動作をどうやって成り立たせるのかがこのアプリの肝です。
それではどのようにプログラムを組んだのか解説していきましょう。
/webapp/tashizan1/forms.py
まずは解答欄のフォームを作成していきますが、今回は簡単にするために1つの問題=1つの解答だけにしましょう。
今回使うのは数字(整数値)なのでIntegerFieldです。
from django import forms
class Tashizan1Form(forms.Form):
answer1 = forms.IntegerField(min_value=0)
今回は正の数の足し算としたいので、「min_value=0」とすることで負の数を入力できなくしています。
ちなみに必ず入力を促したいということで「required=True」をつけてもいいですが、デフォルトで「required=True」となっているようなのでどちらでもかまいません。
またこれまでと違い、初期値は必要ないので、設定していません。
/webapp/tashizan1/views.py
次にviews.pyを修正していきます。
ということでこんな感じです。
from django.shortcuts import render
from django.http import HttpResponse
from .forms import Tashizan1Form
import sys
sys.path.append('../')
from webapp import definitions
import random
def index(request):
params = definitions.readjson()
params['q1a'] = random.randrange(10)
params['q1b'] = random.randrange(10)
params['forms'] = Tashizan1Form()
return render(request, 'tashizan1/index.html', params)
def answercheck(request):
params = definitions.readjson()
params['q1a'] = int(request.POST['q1a'])
params['q1b'] = int(request.POST['q1b'])
params['ans1'] = params['q1a'] + params['q1b']
params['answer1'] = int(request.POST['answer1'])
if params['answer1'] == params['ans1']:
params['anscheck1'] = '正解!'
else:
params['anscheck1'] = '間違い...'
return render(request, 'tashizan1/answercheck.html', params)
まず今回、ランダム値を使いたいので、「import random」でrandomモジュールをインポートしておきます。
また先ほどのforms.pyを読み込むために「from .forms import Tashizan1Form」を追加しています。
ここからはindex.htmlとanswercheck.htmlでページが処理が変わりますので、別々に解説していきます。
def index(request):
まずはindex.html側の処理です。
ここでは二つのランダムな値を取得し表示すること、そして解答欄のフォームを表示する必要があります。
ランダムな値を取得しているのは、この部分です、
params['q1a'] = random.randrange(10)
params['q1b'] = random.randrange(10)
ちなみにrandomモジュールに関しては、こちらの記事で解説していますので、よかったらどうぞ。
「random.randrange」で括弧内に数字が一つ指定されている場合は、0から指定された数字-1までの中から一つの数字が取得されます。
足し算の勉強をするのは小学生低学年だと思うので、とりあえず1桁の数字の足し算ということで、「10」を指定しました。
また「q1a」、「q1b」としているのは、「Q1a」、「Q1b」、つまり問1の二つの数「a」、「b」という意味で使っています。
そして「params[‘forms’] = Tashizan1Form()」でフォームを読み込んでいます。
def answercheck(request):
次に答え合わせ部分「answercheck.html」の修正です。
ここでは先ほどの「q1a」、「q1b」を読み込み、その二つを用いて、正解を計算した「ans1」を準備。
さらに入力された値「answer1」を取得しています。
params['q1a'] = int(request.POST['q1a'])
params['q1b'] = int(request.POST['q1b'])
params['ans1'] = params['q1a'] + params['q1b']
params['answer1'] = int(request.POST['answer1'])
ここで重要なのは、フォームを作成していないにも関わらず「q1a」と「q1b」の値を「request.POST[‘q1a’]」、「request.POST[‘q1b’]」と取得していることです。
ここの秘密はHTMLファイルを読み解くと分かりますので、とりあえず後回しにします。
あとは計算した答えと入力された値を比較し、正解か不正解かを処理します。
if params['answer1'] == params['ans1']:
params['anscheck1'] = '正解!'
else:
params['anscheck1'] = '間違い...'
これでviews.pyの修正は完了です。
/webapp/tashizan1/templates/tashizan1/index.html
次は問題が表示され、答えを入力する「index.html」の修正です。
とりあえず修正後のindex.htmlはこんな感じです。
{% extends "basetemplates/base.html" %}
{% block title %}
<title>{{ title }}|足し算テスト1</title>
{% endblock %}
{% block content %}
<h1>足し算テスト1</h1>
<form action="{% url 'answercheck' %}" method="post">
{% csrf_token %}
<div class="row">
<div class="col">
{{ q1a }} + {{ q1b }} = {{ forms.answer1 }}
<input type='hidden' name='q1a' value={{q1a}}>
<input type='hidden' name='q1b' value={{q1b}}>
</div>
</div>
<p style="margin:2rem 0rem 0rem 0rem;"></p>
<input type='submit' value="答え合わせ">
</form>
{% endblock %}
ここで重要なのはこの部分です。
{{ q1a }} + {{ q1b }} = {{ forms.answer1 }}
<input type='hidden' name='q1a' value={{q1a}}>
<input type='hidden' name='q1b' value={{q1b}}>
まず「{{ q1a }}」と書くだけで先ほどviews.pyで記述した「params[‘q1a’] = random.randrange(10)」の「params[‘q1a’]」を表示することができます。
つまりHTML上の変数として使用できるわけです。
しかしながらこの場合、ブラウザで表示されたHTML上では変数として認識されるのではなく、値として認識されます。
例えばrandom.randrange(10)でparams[‘q1a’]に「5」が代入されたとしましょう。
その場合、HTML上にはその「5」という数字のみが表示され(str型として)、{{ q1a }}という変数だったことは跡形もなく消え去ってしまいます。
そうなると次の「answercheck.html」にこの変数「q1a」の値を渡すことができません。
そこで「q1a」の値を一度HTML上に保存し、再度views.pyで読み込めるようにしているのが、こちらの部分です。
<input type='hidden' name='q1a' value={{q1a}}>
HTMLのタグで「input」はフォームのタグです。
そして「type=’hidden’」とすることで、隠しフォームとなります。
つまりDjangoのフォームではなく、HTMLのフォームとして見えない形でフォームを作成し、そのフォームに「q1a」の値が入力されたことにしているのです。
そのためviews.pyのanswercheck関数では、これまで通り「request.POST[‘q1a’]」で「q1a」の値が取得できるというわけです。
このことが分かるまでかなり時間がかかったので、この記事が誰かの役に立つといいなぁと特に思っています。
/webapp/tashizan1/templates/tashizan1/answercheck.html
次に答え合わせのページ「answercheck.html」を修正していきます。
{% extends "basetemplates/base.html" %}
{% block title %}
<title>{{ title }}|足し算テスト1</title>
{% endblock %}
{% block content %}
<h1>足し算テスト1</h1>
<form action="{% url 'index' %}" method="post">
{% csrf_token %}
<div class="row">
<div class="col">
{{ q1a }} + {{ q1b }} = {{ answer1 }} {{ anscheck1 }} {{ ans1 }}
</div>
</div>
<p style="margin:2rem 0rem 0rem 0rem;"></p>
<input type='submit' value="もう一回!">
</form>
{% endblock %}
こちらで重要なのはこの部分です。
{{ q1a }} + {{ q1b }} = {{ answer1 }} {{ anscheck1 }} {{ ans1 }}
と言っても単純に先ほどviews.pyのanswercheck関数で取得した値、処理した値を表示しているだけです。
これで全体のプログラミングが完了したので、サーバーを起動し、試してみましょう。
最初にアクセスした時には、「4+8=」という問題が出ました。
正解である「12」を入力し、「答え合わせ」ボタンをクリックしてみましょう。
正解なので「正解!」と表示され、さらに正しい解答である「12」が表示されました。
「もう一回!」をクリックして、もう一度試してみましょう。
今度は「2+4=」という問題が表示されました。
わざと間違えて「3」を入力してみましょう。
「間違い…」と正しい答えである「6」が表示されました。
これで足し算テストアプリの基本となるプログラムができました。
次回は問題の数を増やして、index.htmlのレイアウトを整えていきましょう。
ではでは今回はこんな感じで。
コメント