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

※ 当サイトではアフィリエイト広告を利用しています。リンクは広告リンクも含みます。

この記事は約12分で読めます。
広告

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

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

何もインストールしないでも無料のWEBサービスPaizaCloudで
完成品お名前.comVPS(有料)にデプロイが作れます。
完成品Renderデプロイ(これはRender上で動かしてる。表示するまで数分かかることがあります)が作れます。

当記事はデーター入力→セッション保存→描画関数へのデーターの受け渡しが
特徴の記事となっております。
なぜセッション保存を使っているかというと、入力されたデータをもとに描画までいければいいのですがやり方がわかりません。そこで一旦imgのリンクとしてhtmlファイルを作りレスポスします。そのhtmlファイルがプラウザで描画されるときにimgを取りにDjangoにアクセスしたとき、セッションに保存した入力データを使ってグラフのimgをレスポンスするようにしています。
つまり2回ブラウザとDjangoの間にやり取りが必要になります。1回目の入力データをどこかに保存しておかなければ、2回目のリクエストで描画するときに入力データがないのでグラフを作ることができなくなります。

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

Pyscriptを使うと簡単に同じようなことができます。

単純なグラフならVueを使うと見た目がよくなります。

MatplotlibをWebに表示するならStreamlitがおすすめ。

広告

PaizaCloudで動かすグラフ描画

Django定番部分

PaizaCloudで作ります。
PaizaCloud 使い方はこちらを参考にしてください。
その際Herokuへのデプロイを考えている場合
データベース:PostgreSQLを選択してください。
選択しても標準のSQLiteで動かせます。
多分セッションもクッキーで保存しているので今回データベースはいらないと思います。

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から呼ばれる関数やクラス。

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
#シーケンスのコードをインポート
import time
#グラフ作成
import numpy as np
#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", {'xvalue': xvalue,'yvalue': yvalue})
        
#グラフ作成
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(",")
    x=list(map(int, x))
    y1=request.session['yvalue']
    y=y1.split(",")
    y=list(map(int, y))
    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="{{ xvalue }}" id="xvalue" name="xvalue"> 例1,2,3,4,5,6,7</label>
		<br>
		<label>Y: 
        	<input type="text" value="{{ yvalue }}" 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へのデプロイ

Herokuは2022/11末に無料枠がなくなるので今はRailwayを使っています。

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

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

requirements.txtはmatplotlibも今回必要です。
django
gunicorn

matplotlib
最終的にはdjango-herokuも追加されます。

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

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

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




コメント

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