Django
前回、matplotlibで数式の表示の仕方を解説しました。
今回は前回行ったことをもとに、二次関数グラフ表示アプリの数式を改善していきましょう。
また二次関数では頂点や解が重要になってくるので、その計算式も組み込んでいきます。
ということで今回、最初に修正するファイルは/webapp/quadraticfunction/views.pyです。
そして後で/webapp/quadraticfuction/templates/quadraticfuction/index.html を修正していきます。
webapp
├── bmiapp
│ └── ...
├── db.sqlite3
├── index.cgi
├── linearfunction
│ └── ...
├── manage.py
├── quadraticfunction
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── static
│ │ └── quadraticfunction
│ │ └── quadraticfunction.png
│ ├── templates
│ │ └── quadraticfunction
│ │ └── index.html <- 修正
│ ├── tests.py
│ ├── urls.py
│ └── views.py <- 修正
├── static
│ ├── 3pysci_logo.png
│ └── favicon.png
└── webapp
├── __init__.py
├── asgi.py
├── definitions.py
├── params.json
├── settings.py
├── urls.py
└── wsgi.py
/webapp/quadraticfunction/views.pyのグラフタイトルの数式の修正
前回、matplotlibで数式を表示するには$で囲む、そして上付き数字の場合は「^」を使うということを解説しました。
つまり \(y=ax^2+bx+c\) の場合は「$y=ax^2+bx+c$」とすればいいわけです。
ということで views.py の plotting関数の部分を修正するとこうなります。
def plotting(a, b, c, xmax, xmin, ymax, ymin):
xlist = range(xmin, xmax+1)
ylist = []
for i in xlist:
ylist.append(a * i * i + b * i + c)
str_a = checksign(a); str_b = checksign(b); str_c = checksign(c)
if a == 0:
if b == 0:
eq = f'$ y={str_c[0]} $'
elif b != 0:
eq = f'$ y={str_b[1]}x{str_c[2]} $'
elif a != 0:
if b == 0:
eq = f'$ y={str_a[1]}x^2{str_c[2]} $'
elif b != 0:
eq = f'$ y={str_a[1]}x^2{str_b[3]}x{str_c[2]} $'
fig = plt.figure()
plt.clf()
plt.plot(xlist, ylist)
plt.grid()
plt.title(eq,{'fontsize':25})
plt.xlabel("X", {'fontsize':15})
plt.ylabel("Y", {'fontsize':15})
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
plt.savefig("./quadraticfunction/static/quadraticfunction/quadraticfunction.png")
aやbの係数で場合分けをし、それぞれの色を変数eqに格納するところで、matplotlibの数式の形にしています。
そしてそれを「plt.title(eq,{‘fontsize’:25})」とすることで、グラフタイトルとして用いています。
ここまでで一度サーバーを起動し、ブラウザで確認してみるとこんな感じです。
/webapp/quadraticfunction/views.pyに頂点と解の計算を追加
次に二次関数の頂点と解の計算を views.py に追加していきます。
ちなみに二次関数の頂点は
(\(-\frac{b}{2a}, -\frac{b^2-4ac}{4a}\))
です。
また解の公式は
\(x=\frac{-b\pm \sqrt{b^2-4ac}}{2a}\)
です。
ということで頂点のX座標、Y座標、解で「+」の時、「ー」の時の4つの数を新たに追加していきます。
またa=0の時やa=0でさらにb=0の時にはこの公式は使えない(二次関数ではないため)ので、その場合わけも必要です。
しかし場合わけに関してもうすでにされているので、それに対して上記4つの値がどのようになるのか追加していくだけになります。
ということでplotting関数はこんな感じになります。
def plotting(a, b, c, xmax, xmin, ymax, ymin):
xlist = range(xmin, xmax+1)
ylist = []
for i in xlist:
ylist.append(a * i * i + b * i + c)
str_a = checksign(a); str_b = checksign(b); str_c = checksign(c)
if a == 0:
if b == 0:
eq = f'$ y={str_c[0]} $'
solution1 = 'なし'
solution2 = 'なし'
elif b != 0:
eq = f'$ y={str_b[1]}x{str_c[2]} $'
solution1 = str(round(-c/b),2)
solution2 = 'なし'
x_vertex = 'なし'
y_vertex = 'なし'
elif a != 0:
if b == 0:
eq = f'$ y={str_a[1]}x^2{str_c[2]} $'
elif b != 0:
eq = f'$ y={str_a[1]}x^2{str_b[3]}x{str_c[2]} $'
solution1 = str(round((-b + np.sqrt(b * b - 4 * a * c))/(2 * a), 2))
solution2 = str(round((-b - np.sqrt(b * b - 4 * a * c))/(2 * a), 2))
x_vertex = str(round(-b/(2 * a), 2))
y_vertex = str(round(-(b * b - 4 * a * c)/(4 *a), 2))
fig = plt.figure()
plt.clf()
plt.plot(xlist, ylist)
plt.grid()
plt.title(eq,{'fontsize':25})
plt.xlabel("X", {'fontsize':15})
plt.ylabel("Y", {'fontsize':15})
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
plt.savefig("./quadraticfunction/static/quadraticfunction/quadraticfunction.png")
return x_vertex, y_vertex, solution1, solution2
頂点のX座標を「x_vertex」、「Y座標をy_vertex」、公式の+の時の解を「solution1」、ーの時の解を「solution2」としました。
そして最後にそれらの値を返すようにしてあります(return x_vertex, y_vertex, solution1, solution2の部分)。
plotting関数で返された値を受け取らなければなりません。
それを修正した最終的なプログラムがこちらです。
from django.shortcuts import render
from django.http import HttpResponse
from .forms import QFForm
import numpy as np
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
import sys
sys.path.append('../')
from webapp import definitions
def plotting(a, b, c, xmax, xmin, ymax, ymin):
xlist = range(xmin, xmax+1)
ylist = []
for i in xlist:
ylist.append(a * i * i + b * i + c)
str_a = checksign(a); str_b = checksign(b); str_c = checksign(c)
if a == 0:
if b == 0:
eq = f'$ y={str_c[0]} $'
solution1 = 'なし'
solution2 = 'なし'
elif b != 0:
eq = f'$ y={str_b[1]}x{str_c[2]} $'
solution1 = str(round(-c/b),2)
solution2 = 'なし'
x_vertex = 'なし'
y_vertex = 'なし'
elif a != 0:
if b == 0:
eq = f'$ y={str_a[1]}x^2{str_c[2]} $'
elif b != 0:
eq = f'$ y={str_a[1]}x^2{str_b[3]}x{str_c[2]} $'
solution1 = str(round((-b + np.sqrt(b * b - 4 * a * c))/(2 * a), 2))
solution2 = str(round((-b - np.sqrt(b * b - 4 * a * c))/(2 * a), 2))
x_vertex = str(round(-b/(2 * a), 2))
y_vertex = str(round(-(b * b - 4 * a * c)/(4 *a), 2))
fig = plt.figure()
plt.clf()
plt.plot(xlist, ylist)
plt.grid()
plt.title(eq,{'fontsize':25})
plt.xlabel("X", {'fontsize':15})
plt.ylabel("Y", {'fontsize':15})
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
plt.savefig("./quadraticfunction/static/quadraticfunction/quadraticfunction.png")
return x_vertex, y_vertex, solution1, solution2
def checksign(val):
if val == 0:
return '0','','',''
elif val == 1:
return '1','','+1','+'
elif val == -1:
return '-1','-','-1',"-"
elif val > 0:
return f'{val}',f'{val}',f'+{val}',f'+{val}'
elif val < 0:
return f'{val}',f'{val}',f'{val}',f'{val}'
def index(request):
params = definitions.readjson()
initial_val = {
'a':1,
'b':0,
'c':0,
'xmin':-10,
'xmax':10,
'ymin':-10,
"ymax":10,
}
params['forms']= QFForm(request.POST or None, initial=initial_val)
x_vertex, y_vertex, solution1, solution2 = plotting(initial_val['a'], initial_val['b'],initial_val['c'], initial_val['xmax'], initial_val['xmin'], initial_val['ymax'], initial_val['ymin'])
params['x_vertex'] = x_vertex
params['y_vertex'] = y_vertex
params['solution1'] = solution1
params['solution2'] = solution2
if (request.method == 'POST'):
a = int(request.POST['a'])
b = int(request.POST['b'])
c = int(request.POST['c'])
xmax = int(request.POST['xmax'])
xmin = int(request.POST['xmin'])
ymax = int(request.POST['ymax'])
ymin = int(request.POST['ymin'])
params['forms'] = QFForm(request.POST)
x_vertex, y_vertex, solution1, solution2 = plotting(a, b, c, xmax, xmin, ymax, ymin)
params['x_vertex'] = x_vertex
params['y_vertex'] = y_vertex
params['solution1'] = solution1
params['solution2'] = solution2
return render(request, 'quadraticfunction/index.html', params)
変更したのは以下の二つの部分です。
x_vertex, y_vertex, solution1, solution2 = plotting(initial_val['a'], initial_val['b'],initial_val['c'], initial_val['xmax'], initial_val['xmin'], initial_val['ymax'], initial_val['ymin'])
params['x_vertex'] = x_vertex
params['y_vertex'] = y_vertex
params['solution1'] = solution1
params['solution2'] = solution2
x_vertex, y_vertex, solution1, solution2 = plotting(a, b, c, xmax, xmin, ymax, ymin)
params['x_vertex'] = x_vertex
params['y_vertex'] = y_vertex
params['solution1'] = solution1
params['solution2'] = solution2
どちらもplotting関数から戻ってきた値をそれぞれの変数に格納し、さらにparamsに格納しています。
/webapp/quadraticfuction/templates/quadraticfuction/index.html の修正
では次にindex.htmlを修正していきますが、修正後の<!–main–>部分のプログラムはこんな感じです。
<!-- main -->
<div class="col-sm-9" style="text-align: center; margin:2rem 0rem 2rem 0rem;">
<form action="/quadraticfunction/" method="post">
{% csrf_token %}
<table style="margin-left:auto; margin-right:auto;">
<tr><td style="text-align: right;">{{ forms.a.label}}:</td><td>{{ forms.a }}</td><td style="text-align: right;">{{ forms.b.label }}:</td><td>{{ forms.b }}</td><td style="text-align: right;">{{ forms.c.label }}:</td><td>{{ forms.c }}</td></tr>
<tr><td style="text-align: right;">{{ forms.xmax.label }}:</td><td>{{ forms.xmax }}</td><td style="text-align: right;">{{ forms.xmin.label }}:</td><td>{{ forms.xmin }}</td><td></td></tr>
<tr><td style="text-align: right;">{{ forms.ymax.label }}:</td><td>{{ forms.ymax }}</td><td style="text-align: right;">{{ forms.ymin.label }}:</td><td>{{ forms.ymin }}</td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td><td style="text-align: right;"><input type='submit' value="click"></td></tr>
</table>
</form>
<img src="{% static 'quadraticfunction/quadraticfunction.png' %}">
<p></p>
<table style="margin-left:auto; margin-right:auto;">
<tr><td style="text-align: right;"><font size="7">頂点の座標: </font></td><td style="text-align: center;"><font size="7">({{x_vertex}}, {{y_vertex}})</font></td></tr>
<tr><td style="text-align: right;"><font size="7">解: </font></td><td style="text-align: center;"><font size="7">{{solution1}}, {{solution2}}</font></td></tr>
</table>
</div>
<!-- /main -->
ただ今回追加した部分はこの部分のみです。
<p></p>
<table style="margin-left:auto; margin-right:auto;">
<tr><td style="text-align: right;"><font size="7">頂点の座標: </font></td><td style="text-align: center;"><font size="7">({{x_vertex}}, {{y_vertex}})</font></td></tr>
<tr><td style="text-align: right;"><font size="7">解: </font></td><td style="text-align: center;"><font size="7">{{solution1}}, {{solution2}}</font></td></tr>
</table>
グラフ画像の後に先ほどの頂点と解を表示しています。
その際、テーブルを使うことで内容を整列させています。
またテーブル自身も中央寄せしています(<table style=”margin-left:auto; margin-right:auto;”>)。
またデフォルトの文字サイズが結構小さかったので、それぞれ文字に関しては、「<font size=”7″>頂点の座標:</font>」とるすことで文字のサイズを大きくしています。
ちなみにフォントサイズは1から7の7段階で、デフォルトは3です。
あとはそれぞれの文字を場所によって右寄せ(style=”text-align: right;”)や中央寄せ(style=”text-align: center;”)をしています。
これで再度ブラウザで確認してみるとこうなります。
頂点の座標と解が表示されるようになりました。
これで合計3つのWebアプリができたということで、次回からは全部をまとめるウェブサイトのインデックスページを作っていきたいと思います。
ではでは今回はこんな感じで。
コメント