【Django入門】データ入力してグラフを描画する方法【Matplotlib】

この記事は約11分で読めます。

データーを入力しグラフを表示するアプリの簡単な例になります。
formで入力したデータをセッションを利用して
描画する関数に渡しています。
Django初心者でもPythonのプログラムを公開デプロイできるように
手順を書いてあります。

Djangoについて基礎から知りたい人は私の他の記事を参考にしてください。

何もインストールしないでも無料のWEBサービスPaizaCloudで
完成品(これはHeroku上で動かしてる)が作れます。


当記事はデーター入力→セッション保存→描画関数へのデーターの受け渡しが
特徴の記事となっております。
なのでDjangoでMatplotlibの描画に関する解説はありません。

Matplotlibを描画させる詳細部分については
こちらの記事を参考にさせていただきました。
MatplotlibのグラフをDjangoで使ってみた

PaizaCloudで動かすグラフ描画

Django定番部分

PaizaCloudで作ります。
PaizaCloud 使い方はこちらを参考にしてください。
その際Herokuへのデプロイを考えている場合
データベース:PostgreSQLを選択してください。
選択しても標準のSQLiteで動かせます。
この記事もSQLiteで動かしてからPostgresへ変更してます。

PaizaCloudの左にあるターミナルをクリック
以下のコードを入力

matplotlib_appという名前でプロジェクトの作成
django-admin startproject matplotlib_app 

matplotlib_appディレクトリへ移動
cd matplotlib_app

mtplt_appという名前でアプリ作成
python manage.py startapp mtplt_app
settings.py変更
matplotlib_app/matplotlib_app/settings.pyをダブルクリック

以下のように2か所変更
・ホストを全部許可する。
・アプリを追加

ALLOWED_HOSTS = [] → ALLOWED_HOSTS = ['*']

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
  'mtplt_app.apps.MtpltAppConfig',      
#追加部分 mtplt_app/apps.pyにあるclass MtpltAppConfig(AppConfig):のクラス名を追加。'mtplt_app', だけでも動く
]

どこでもいいので下の1行追加
SESSION_ENGINE ="django.contrib.sessions.backends.signed_cookies"#クッキーで保存

今後ファイルを変更したら各Window左上の保存をクリック。
車両通行止めと同じマークが出ている場合は保存完了してます。

URL設定urls.py

URLと処理を紐づけします。
urls.pyはプロジェクト(matplotlib_app)とアプリ(mtplt_app)にそれぞれ必要です。
プロジェクト側のurls.pyは毎回同じです。
path(”の”はサーバーに割り当てられている大元のアドレスになります。
PaizaCloudの場合は後程プログラムを実行すればわかりますが
https://localhost-個人別の名前.paiza-user-free.cloud:8000/が大元となります。
なのでpath(”,include(“mtplt_app.urls”)),は上記アドレスにアクセスしたら
mtplt_app/urls.pyに行けという意味です。

プロジェクト(matplotlib_app)のurls.pyを変更

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include("mtplt_app.urls")),
]

アプリ(mtplt_app)のurls.pyは最初ないので
mtplt_appを右クリックして新規ファイル作成でurls.py作成
中身を以下にします。

from django.urls import path
from . import views

app_name    = "mtplt_app"
urlpatterns = [ 
    path('', views.MatplotlibView.as_view(), name="index"),
    path('plot/', views.get_svg, name='plot'),
]

これもpath(’’なので大元のアドレスにアクセスしたら
views.pyのMatplotlibView.as_view()を実行しろという意味です。
as_view()は継承元のViewクラスのメソッドでviewオブジェクトを生成します。
Viewクラスを継承したクラスを実行する場合はこの形で共通のようです。
path(‘plot/’はresult.htmlを表示したときに読みだされます。
ここでグラフを描画しています。
目次へ

データ処理 views.py

Viewクラス(get()、post()などHTTPメソッドに特化したビュークラス)を
継承してMatplotlibViewをつくります。
このViewクラスはgetとpostが来たときの処理を書けば済みます。
postでセッションのクリアと新たにxとyの入力値を取得
描画する関数にセッションでデータを渡しています。

セッションを利用できるのは、
どんな関数でも(request):って書けばいいのかと思ってましたが
requestを引数として持てるクラスや関数に限られるようです。
ユーザーのrequestを受けるところ。
つまりurls.pyから呼ばれる関数やクラス。
views.py

import matplotlib
#バックエンドを指定
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import io
from django.http import HttpResponse

from django.shortcuts import render
#クラスベースのビューを作るため
from django.views import View

#Viewを継承してGET文、POST文の関数を作る
class MatplotlibView(View):

    def get(self, request, *args, **kwargs):
        return render(request,"mtplt_app/result.html")

    def post(self, request, *args, **kwargs):
        #セッションクリア
        request.session.clear()
        #セッション&クッキー 削除
        request.session.flush()

        xvalue=request.POST["xvalue"]
        yvalue=request.POST["yvalue"]
        mode=request.POST["mode"]
        if xvalue !="" and yvalue !="":

            request.session['xvalue']=xvalue
            request.session['yvalue']=yvalue
            request.session['mode']=mode
        return render(request,"mtplt_app/result.html")
        
#グラフ作成
def setPlt(x,y,mode):

    fig, ax = plt.subplots(facecolor='white') 
    if mode =="plot":
        ax.plot(x,y)
        plt.title("X-Y plot")
    elif mode == "bar":
        ax.bar(x,y)
        plt.title("X-Y var")
    plt.xlabel("X")
    plt.ylabel("Y")
# SVG化
def plt2svg():
    buf = io.BytesIO()
    plt.savefig(buf, format='svg', bbox_inches='tight')
    s = buf.getvalue()
    buf.close()
    return s

# 実行するビュー関数
def get_svg(request):
    x1=request.session['xvalue']
    x=x1.split(",")
    y1=request.session['yvalue']
    y=y1.split(",")
    mode=request.session['mode']
    setPlt(x,y,mode)  
    svg = plt2svg()  #SVG化
    plt.cla()  # グラフをリセット
    response = HttpResponse(svg, content_type='image/svg+xml')
    return response

目次へ

表示 Template

mtplt_appを右クリック、新規ディレクトリでtemplatesディレクトリ作成
その下にもう1個mtplt_appディレクトリ作成
templates/mtplt_appを右クリックして新規ファイル作成でresults.html作成
results.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Matplotlibアプリ</title>

</head>
    <body>
        <p></p>
            <h2>Matplotlibアプリ</h2>
        <br>
        <p>XとYにそれぞれカンマ(,)区切りでデータを入力→グラフタイプを選択して送信を押せば表示します。</p>
	<form action="" method="POST">
	    {% csrf_token %}
 		<label>X: 
        	<input type="text" value="" id="xvalue" name="xvalue"> 例1,2,3,4,5,6,7</label>
		<br>
		<label>Y: 
        	<input type="text" value="" id="yvalue" name="yvalue"> 例10,20,30,40,50,60,70</label>

		<br>
		<input type="radio" id="mode" name="mode" value="plot" checked="checked">折れ線
		<input type="radio" id="mode" name="mode" value="bar">棒グラフ
		<br>

        <input type="submit" value="送信">
	</form> 
	    <p>基本的な動作確認用なので真ん中の数字を減らすとy軸表示がおかしくなります。</p>
        <img src="{% url 'mtplt_app:plot' %}" width=600 height=600>
    </body>
</html>
python manage.py runserverでプログラムが実行できます。
PaizaCloudの左の8000をクリックすると表示します。

目次へ

Herokuへのデプロイ

手順としてまずデータベースをSQLiteから
PostgreSQLへ変更(HerokuはPostgresSQLを使っているため)
PaizaCloudで動作確認してからHeroku用へ変更しています。

こちらの記事のデータベース接続設定(プログラム)からやってください。
その際PostgreSQLインストールとデータベース作成(ターミナルで作業)
「マイグレートして項目を作成 python manage.py migrate」までやればOKです。
python manage.py shellのデータベースへデータを書き込む部分は必要ありません。
PaizaCloudでデータベースをPostgresSQLへの変更は完了です。
動作確認して次にHerokuで動かすをやってください。

requirements.txtはmatplotlibも今回必要です。
django
gunicorn
psycopg2-binary==2.8.6
matplotlib
最終的にはdjango-herokuも追加されます。

「静的ファイル対応」は不要です。
静的ファイルとは画像やcss、jsを指します。
今回いずれも使用していないのでやる必要がありません。

デプロイ完了でデータベースに項目作って初期値を入れるという部分(run console以下)は不要です。
デプロイ完了したら右上のOpen Appで起動できます。
目次へ

MENTAやってます(ichige)
イチゲをOFUSEで応援する




コメント

タイトルとURLをコピーしました