🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

792閲覧

SQLクエリで取得した値を他の関数で使用したいです

taro__

総合スコア1

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/01/27 01:23

編集2021/01/27 06:28

前提・実現したいこと

djangoでSQLクエリから取得した値を使用して、グラフを表示したいです。
しかし、取得したい変数は関数を使用して値を取得したため、ローカル変数であり、現在解決方法がわかりません。(コード上のdeficiency_taroの部分です)
他の質問に記載されていた、'global 変数' のようにしてもコードを実行できなかったため今回質問させていただきます。
初歩的な質問かと思いますがどうぞよろしくおねがいします。

発生している問題・エラーメッセージ

グラフの画像が表示されません。

試したこと

以下のコードを実行しました。

該当のソースコード

views.py

import io import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import base64 class MoneyListView(ListView): model = Money context_object_name = 'money_list' paginate_by = 3 #db aggregate def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) #average avg_amount = Money.objects.aggregate(Sum('amount'))['amount__sum']/3 context["avg_amount"] = avg_amount #payment/per name=Taro pay_taro = Money.objects.filter(name='Taro').aggregate(Sum('amount'))['amount__sum'] context["pay_taro"] = pay_taro #deficiency/per name=Taro deficiency_taro = avg_amount - pay_taro context["deficiency_taro"] = deficiency_taro #graph def create_graph(x_list, y_list): plt.cla() plt.plot(x_list, y_list) plt.xlabel('名前') plt.ylabel('過不足') #convertion def get_image(): buffer = ioByteIO() plt.saveconfig(buffer, format='png') image_png = buffer.getvalue() graph = base64.b64encode(image_png) graph = graph.decode('utf-8') buffer.close() return graph #send html def home(request): x_list = ['Taro'] y_list = [deficiency_taro] create_graph(x_list, y_list) graph = get_image() return render(request, 'differential/home.html', {'graph': graph})

補足情報(FW/ツールのバージョンなど)

python 3.9.1
django 3.1.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

plasticgrammer

2021/01/27 02:58

わからない箇所があるので確認させてください。 home関数にて使用している「utils」の実体はMoneyListViewクラスかと思いますが、どこで作成されているのでしょうか。
taro__

2021/01/27 23:25 編集

返信ありがとうございます。 「utils」というコードはhome関数でのみ書いています。 どこかで作成する必要があるのでしょうか。 知識不足で申し訳ありません。 よろしくおねがいします。
plasticgrammer

2021/01/27 04:04

> 「utils」というコードはhome関数でのみ書いています。 > どこかで作成する必要があるのでしょうか。 そもそも、なぜ「utils.関数名」としているのでしょうか。 その理由がわからないのでなんとも言えませんが、なくても良いと思っています。
taro__

2021/01/27 23:26 編集

わかりました。 utilsを削除し以下のコードを実装しましたが、相変わらずグラフが表示されません。 解決策がわからないため、ご教授いただけないでしょうか。 views.py #send html def home(request): x_list = ['Taro', 'Koki', 'Kaze'] y_list = [deficiency_taro, deficiency_koki, deficiency_kaze] utils.create_graph(x_list, y_list) graph = get_image() return render(request, 'differential/home.html', {'graph': graph}) htmlファイル <img src="data:image/png;base64, {{ graph | safe }} " alt="">
plasticgrammer

2021/01/27 05:53

utils.create_graph 上記の「utils.」も削除しましたか? 修正後のソースは質問側を修正くださいますようお願いします。 修正後、何かエラーが発生しているのでしょうか。
taro__

2021/01/27 06:04

すみません。忘れていました。 上記の「utils.」を削除後、再度 ./manage.py runserver を実行したところ、エラーは発生しませんでした。 しかし、画像は表示されませんでした。 view.py #send html def home(request): x_list = ['Taro', 'Koki', 'Kaze'] y_list = [deficiency_taro, deficiency_koki, deficiency_kaze] create_graph(x_list, y_list) graph = get_image() return render(request, 'differential/home.html', {'graph': graph}) htmlファイル <img src="data:image/png;base64, {{ graph | safe }} " alt="">
plasticgrammer

2021/01/27 06:13

修正後のソースは質問側を修正くださいますようお願いします。 状況が進んだようですので、一旦回答を記載します。
guest

回答2

0

ベストアンサー

・ioByteIO → io.BytesIO
・plt.saveconfig → plt.savefig
get_context_data()内で return contextしていないので、設定したデータがテンプレートに渡されていません。
MoneyListView.home()でグラフデータのレンダリングをして、テンプレートに渡そうとしているようですが、 MoneyListViewのget_data_context()の中でデータベースから取得し計算したデータを、
どうやってグラフデータ作成に利用するか、というところについては、
グラフ画像のバイナリをBase64エンコードしてテンプレートに渡すというアプローチをとろうとされているようなので、グラフデータ作成処理部分は汎用ビューから切り離し、エンコード結果を、(データベースから取得し計算したデータと一緒に)contextとして渡した方がすっきりするのではないかと思いました。

以上をまとめたコードが以下です。データの設定等は愚直なままですが元のコード自体がそうなのであしからず。

views.py

python

1# views.py 2 3import io 4import matplotlib 5import matplotlib.pyplot as plt 6import base64 7from django.views.generic import ListView 8from django.db.models import Sum 9from .models import Money 10matplotlib.use('Agg') 11 12 13class MoneyListView(ListView): 14 model = Money 15 context_object_name = 'money_list' 16 template_name = 'moneyapp/money_list.html' 17 18 # db aggregate 19 def get_context_data(self, **kwargs): 20 context = super().get_context_data(**kwargs) 21 avg_amount = Money.objects.aggregate(Sum('amount'))['amount__sum'] / 3 22 context["avg_amount"] = avg_amount 23 24 # payment/per name=Taro 25 pay_taro = Money.objects.filter(name='Taro').aggregate(Sum('amount'))['amount__sum'] 26 pay_jiro = Money.objects.filter(name='Jiro').aggregate(Sum('amount'))['amount__sum'] 27 pay_koki = Money.objects.filter(name='Koki').aggregate(Sum('amount'))['amount__sum'] 28 pay_kaze = Money.objects.filter(name='Kaze').aggregate(Sum('amount'))['amount__sum'] 29 context["pay_taro"] = pay_taro 30 context["pay_jiro"] = pay_jiro 31 context["pay_koki"] = pay_koki 32 context["pay_kaze"] = pay_kaze 33 34 # deficiency/per name=Taro 35 deficiency_taro = avg_amount - pay_taro 36 deficiency_jiro = avg_amount - pay_jiro 37 deficiency_koki = avg_amount - pay_koki 38 deficiency_kaze = avg_amount - pay_kaze 39 context["deficiency_taro"] = deficiency_taro 40 context["deficiency_jiro"] = deficiency_jiro 41 context["deficiency_koki"] = deficiency_koki 42 context["deficiency_kaze"] = deficiency_kaze 43 44 x_list = ['Taro', 'Jiro', 'Koki', 'Kaze'] 45 y_list = [deficiency_taro, deficiency_jiro, deficiency_koki, deficiency_kaze] 46 create_graph(x_list, y_list) 47 graph = get_image() 48 49 # グラフデータもcontextに。 50 context["graph"] = graph 51 52 # contextを返す。 53 return context 54 55# グラフデータ作成処理部分 56def create_graph(x_list, y_list): 57 plt.cla() 58 plt.bar(x_list, y_list) 59 plt.xlabel('name') 60 plt.ylabel('deficiency') 61 62 63def get_image(): 64 buffer = io.BytesIO() 65 plt.savefig(buffer, format='png') 66 image_png = buffer.getvalue() 67 graph = base64.b64encode(image_png) 68 graph = graph.decode('utf-8') 69 buffer.close() 70 return graph 71

urls.py

python

1# urls.py 2 3from django.urls import path 4from . import views 5app_name = 'plot' 6urlpatterns = [ 7 path('index/', views.MoneyListView.as_view(), name='index'), 8]

 

money_list.html

HTML

1{% extends 'base.html' %} 2{% block content %} 3<h1>Graph</h1> 4 5<img src="data:image/png;base64, {{ graph | safe }} " alt=""> 6 7<table> 8 <tr> 9 <th></th> 10 <th>Taro</th> 11 <th>Jiro</th> 12 <th>Koki</th> 13 <th>Kaze</th> 14 15 </tr> 16 <tr> 17 <td>payment</td> 18 <td>{{ pay_taro |floatformat:0 }}</td> 19 <td>{{ pay_jiro |floatformat:0 }}</td> 20 <td>{{ pay_koki |floatformat:0 }}</td> 21 <td>{{ pay_kaze |floatformat:0 }}</td> 22 </tr> 23 <tr> 24 <td>deficiency</td> 25 <td>{{ deficiency_taro |floatformat:0 }}</td> 26 <td>{{ deficiency_jiro |floatformat:0 }}</td> 27 <td>{{ deficiency_koki |floatformat:0 }}</td> 28 <td>{{ deficiency_kaze |floatformat:0 }}</td> 29 </tr> 30 31</table> 32{% endblock %}

ディレクトリ構成

text

1myapp/ 2├ money_app/ 3| ├ migrations/ 4| ├ templates/ 5| | ├ money_app/ 6| | | └ money_list.html 7| | └ base.html 8| ├ admin.py 9| ├ apps.py 10| ├ models.py 11| ├ urls.py 12| └ views.py 13├ myapp/ 14├  └・・・ 15├ ・・・ 16├ manage.py 17└ db.sqlite3

投稿2021/01/27 16:24

編集2021/01/27 23:38
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

taro__

2021/01/27 23:21 編集

返信ありがとうございます! 表示できました!
taro__

2021/01/29 15:09

データの設定等は愚直なままだとは思いますが、よりよい方法があればご教授いただけないでしょうか。 models.py from django.db import models CHOICE = (('Taro', 'Taro'), ('Koki', 'Koki'), ('Kaze', 'Kaze')) class Money(models.Model): purpose = models.CharField('用途', max_length=100) name = models.CharField( '名前', max_length=100, choices=CHOICE ) amount = models.IntegerField('金額(円)') posted_date = models.DateTimeField('時刻', auto_now_add=True) class Meta: ordering = ['-posted_date'] def __str__(self): return self.purpose
退会済みユーザー

退会済みユーザー

2021/01/29 15:23 編集

コメント欄だとインデントがわからなくなるので、別の質問を立ててもらってもいいでしょうか。 あと、その時もなるべくプロジェクトの全部のソース及びディレクトリ構成を載せていただけると、プログラムの改善や理解の上で助かります。 すくなくとも、models.py, templatesフォルダ内のキモとなるhtmlファイル、views.py、urls.pyは全部記載してください。ディレクトリ構成も可能な限り示してください。 import文も勝手に消さないでください。 なせなら、djangoは影響が複数のファイルに亘り、ディレクトリ内の位置やファイル名が変わっただけでも動かなくなるからです。 たとえば私は上記の回答するにあたって、 ・質問文に記載されていないimport文をエラーが出なくなるまで補完したり、 ・model(Money)をコードから推測して作ったり、 ・urls.pyやtemplate下のファイルを自分で作ったり ・その他ダミー用のデータを作ったり、 ・多分setting.pyのここはこうなってるんだろうな~ 等、うまく動かすためにあらゆるところを何回も何回も試行錯誤しながら補完して回答したわけです。 もし全部のソースを載せていただいたなら、このような手間もないので。
taro__

2021/01/30 10:55 編集

知識不足で大変申し訳ございません。 https://teratail.com/questions/319425 に質問しましたので、解決策をご教授いただけないでしょうか。 ソースコードはgithubのurlを記載させていただきました。 念の為、こちらにも記載させていただきます。
退会済みユーザー

退会済みユーザー

2021/01/30 06:02

ご協力ありがとうございます。
guest

0

home関数にて使用している「utils.」は不要かと思います。

エラーなく動くようであれば、ブラウザの開発者ツールを使用して、imgのsrc属性に期待通りの値が設定されているか確認してみてください。

投稿2021/01/27 06:14

plasticgrammer

総合スコア629

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

taro__

2021/01/27 06:26

<img src="data:image/png;base64, {{ graph | safe }} " alt="">と入力しましたが、 確認すると、<img src="data:image/png;base64," alt="">でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問