Django
前回は初期値を持ったフォームを作成する方法を解説しました。
今回はMatplotlibを使って、グラフを表示していきたいと思います。
今回使うファイルは「/webapp/linearfunction/templates/linearfunction/index.html」と「/webapp/linearfunction/views.py」の二つです。
webapp
├── bmiapp
│ └── ...
├── db.sqlite3
├── index.cgi
├── linearfunction
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── templates
│ │ └── linearfunction
│ │ └── index.html <- 修正
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ ├── forms.py
│ └── views.py <- 修正
├── manage.py
├── static
│ ├── 3pysci_logo.png
│ └── favicon.png
└── webapp
├── __init__.py
├── asgi.py
├── definitions.py
├── params.json
├── settings.py
├── urls.py
└── wsgi.py
それでは始めていきましょう。
/webapp/linearfunction/views.py
views.pyの修正後のプログラムはこうなります。
from django.shortcuts import render
from django.http import HttpResponse
from .forms import LFForm
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
import sys
sys.path.append('../')
from webapp import definitions
def plotting(a, b, xmax, xmin, ymax, ymin):
xlist = range(xmin, xmax+1)
ylist = []
for i in xlist:
ylist.append(a * i + b)
eq = str(a) + "x+" + str(b)
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("./linearfunction/static/linearfunction/linearfunction.png")
def index(request):
params = definitions.readjson()
initial_val = {
'a':1,
'b':0,
'xmin':-10,
'xmax':10,
'ymin':-10,
"ymax":10,
}
params['forms']= LFForm(request.POST or None, initial=initial_val)
plotting(initial_val['a'], initial_val['b'], initial_val['xmax'], initial_val['xmin'], initial_val['ymax'], initial_val['ymin'])
if (request.method == 'POST'):
a = int(request.POST['a'])
b = int(request.POST['b'])
xmax = int(request.POST['xmax'])
xmin = int(request.POST['xmin'])
ymax = int(request.POST['ymax'])
ymin = int(request.POST['ymin'])
params['forms'] = LFForm(request.POST)
plotting(a, b, xmax, xmin, ymax, ymin)
return render(request, 'linearfunction/index.html', params)
まず重要なのがインポートです。
matplotlibをインポートするのですが、いつものように「from matplotlib import pyplot as plt」だけでは正常に動きません。
実際試してみると「python luncher」が起動してしまいます。
そこでバックグラウンドで起動させるコマンドを追加してやります。
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
このように「import matplotlib」をした後に「matplotlib.use(‘Agg’)」とすることで、matplotlibはバックグラウンドで実行されるようになります。
その後、「from matplotlib import pyplot as plt」でpyplotをインポートします。
ちなみにこの順番をこんなふうに変えてしまうと、動かないので注意してください。
import matplotlib
from matplotlib import pyplot as plt
matplotlib.use('Agg')
一次関数の計算
次に一次関数の計算をするプログラム部分を作成していきます。
今回はplottingという関数を作成し、そこで計算をして、グラフにしています。
def plotting(a, b, xmax, xmin, ymax, ymin):
xlist = range(xmin, xmax+1)
ylist = []
for i in xlist:
ylist.append(a * i + b)
eq = str(a) + "x+" + str(b)
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("./linearfunction/static/linearfunction/linearfunction.png")
まずは計算部分から解説していきましょう。
def plotting(a, b, xmax, xmin, ymax, ymin):
xlist = range(xmin, xmax+1)
ylist = []
for i in xlist:
ylist.append(a * i + b)
eq = str(a) + "x+" + str(b)
今回、取得した値は「a」、「b」、「xmax」、「xmin」、「ymax」、「ymin」の6つです。
それらを最初の「def plotting(a, b, xmax, xmin, ymax, ymin):」で指定するように定義しています。
そして「xlist = range(xmin, xmax+1)」でxの値のリスト(xlist)を作成し、そのxのリストから一つずつ値を取り出し(for i in xlist:)、 \(ax+b\) を計算したのち、yの値のリスト(ylist)に格納しています(ylist.append(a * i + b))。
最後の「eq = str(a) + “x+” + str(b)」は式を表示するために文字列としての式を変数eqに格納しています。
グラフの作成と保存
xとyの値のリストができたら、グラフを作成し、図として保存します。
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("./linearfunction/static/linearfunction/linearfunction.png")
今回グラフを作成するにあたって、特殊なことはしていませんので、matplotlibの使い方に関しては過去の記事を参考にしてもらえると助かります。
最後の「plt.savefig(“./linearfunction/static/linearfunction/linearfunction.png”)」がグラフを保存するコマンドです。
ここで「./linearfunction/static/linearfunction/」ということでlinearfunctionフォルダの下に「/static/linearfunction」というフォルダ構造でフォルダを追加することをお忘れなく。
webapp
├── bmiapp
│ └── ...
├── db.sqlite3
├── index.cgi
├── linearfunction
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── templates
│ │ └── linearfunction
│ │ └── index.html
│ ├── static <- 新規作成
│ │ └── linearfunction <- 新規作成
│ │ └── linearfunction.png <- matplotlibにより作成されるグラフのファイル
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ ├── forms.py
│ └── views.py
├── manage.py
├── static
│ ├── 3pysci_logo.png
│ └── favicon.png
└── webapp
├── __init__.py
├── asgi.py
├── definitions.py
├── params.json
├── settings.py
├── urls.py
└── wsgi.py
/webapp/linearfunction/templates/linearfunction/index.html
次にindex.htmlにグラフを表示するためのコマンドを追加していきます。
と言っても特殊なコマンドではなく、matplotlibで作成されたグラフの画像ファイルを表示するだけなので、前に解説したように画像を表示するコマンドを追加するだけです。
ということでメインの部分に「<img src=”{% static ‘画像ファイル’ %}”>」を追加します。
<!-- main -->
<div class="col-sm-9" style="text-align: center; margin:2rem 0rem 2rem 0rem;">
<form action="{% url 'index' %}" 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></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></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></tr>
<tr><td></td><td></td><td></td><td style="text-align: right;"><input type='submit' value="click"></td></tr>
</table>
</form>
<img src="{% static 'linearfunction/linearfunction.png' %}">
</div>
<!-- /main -->
これでサーバーを起動し、グラフが表示されたか確認してみましょう。
グラフが表示されました。
しかしここでちょっと問題点が。
数学的には通常 \(1x+0\) とは書きません。
「1x」の「1」は省略されますし、「+0」も省略され、 \(x\) と書かれるべきです。
また「b」がマイナスになった場合、「+-1」のように「+-」が表示されてしまっています。
このままでは見栄えが悪いので、次回はこの式の表示を修正していきましょう。
ではでは今回はこんな感じで。
コメント