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

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

詳細はこちら
Django

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

データベース

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

Python

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

Q&A

2回答

2450閲覧

TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'を解決したいです。

taro__

総合スコア1

Django

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

データベース

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

Python

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

0グッド

0クリップ

投稿2021/01/30 03:49

編集2021/01/30 06:30

前提・実現したいこと

テストコードを実行した際に発生したエラーを解決したいです。
ランサーバーを起動すると正常に動くのですが、テストコードを実行するとエラーが発生します。
初歩的な質問かもしれませんが、解決策をご教授していただけないでしょうか。

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

型を合わせて計算する方法がわかりません。
データベースの集計した値を avg_amount = Money.objects.aggregate(Sum('amount'))['amount__sum']/3 と代入したのですが、TypeError: unsupported operand type(s) for /: 'NoneType' and 'int' とエラーが出ました。

File "/Users/taro/pj/env/moneypj/money/views.py", line 31, in get_context_data avg_amount = Money.objects.aggregate(Sum('amount'))['amount__sum']/3 TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'

試したこと

型が違うとのことだったため、以下のコードを実行しましたが、解決できませんでした。
avg_amount = int(Money.objects.aggregate(Sum('amount'))['amount__sum'])/3

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

python 3.9.1
django 3.1.5

###追記
画像を用いて質問したかったので、もう一度投稿させていただきます。

金額を入力して割り勘金額を動的に表示するプログラムを実装中です。
画像の赤線部分が今回解決したいエラー箇所です。
イメージ説明

該当のソースコード(views.py)

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) #sum total_amount = Money.objects.aggregate(Sum('amount'))['amount__sum'] context["total_amount"] = total_amount #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 #payment/per name=Koki pay_koki = Money.objects.filter(name='Koki').aggregate(Sum('amount'))['amount__sum'] context["pay_koki"] = pay_koki #payment/per name=Kaze pay_kaze = Money.objects.filter(name='Kaze').aggregate(Sum('amount'))['amount__sum'] context["pay_kaze"] = pay_kaze #deficiency/per name=Taro deficiency_taro = avg_amount - pay_taro context["deficiency_taro"] = deficiency_taro #deficiency/per name=Koki deficiency_koki = avg_amount - pay_koki context["deficiency_koki"] = deficiency_koki #deficiency/per name=Kaze deficiency_kaze = avg_amount - pay_kaze context["deficiency_kaze"] = deficiency_kaze #create graph x_list = ['Taro', 'Koki', 'Kaze'] y_list = [pay_taro, pay_koki, pay_kaze] create_graph(x_list, y_list) graph = get_image() context['graph'] = graph return context

該当のソースコード(htmlファイル)

{% extends 'base.html' %} {% block body %} <div class="container"> <p><a href="{% url 'create' %}" class="btn btn-secondary">追加</a></p> {% for money in object_list %} <div class="alert alert-secondary" role="alert"> <p>{{ money.purpose }}</p> <p> {{ money.name }} : {{ money.amount }}円 </p> <a href="{% url 'detail' money.pk %}" class="btn btn-secondary btn-sm" tabindex="-1" role="button" aria-disabled="true">詳細</a> <a href="{% url 'update' money.pk %}" class="btn btn-secondary btn-sm" tabindex="-1" role="button" aria-disabled="true">編集</a> <a href="{% url 'delete' money.pk %}" class="btn btn-secondary btn-sm" tabindex="-1" role="button" aria-disabled="true">削除</a> </div> {% endfor %} <div class="alert alert-primary" role="alert"> <h6>総合計金額</h6> <p>{{ total_amount }}円</p> <h6>割り勘金額</h6> <p>{{ avg_amount|floatformat:1 }}円</p> <h6>現在の支払金額</h6> <p>Taro:{{ pay_taro }}円<br> Koki:{{ pay_koki }}円<br> Kaze:{{ pay_kaze }}円</p> <h6>支払い不足金額</h6> <p>Taro:{{ deficiency_taro|floatformat:1 }}円<br> Koki:{{ deficiency_koki|floatformat:1 }}円<br> Kaze:{{ deficiency_kaze|floatformat:1 }}円</p> <p> ***<br> 〜支払い不足金額について〜<br> +n円:n円払ってもらい過ぎ<br> -n円:n円払い過ぎ<br> *** </p> </div> <img src="data:image/png;base64, {{ graph | safe }} " alt=""> <nav aria-label="Page navigation example"> <ul class="pagination"> {% if page_obj.has_previous %} <li class="page-item"> <a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous"> <span aria-hidden="true">&laquo;</span> <span class="sr-only">Previous</span> </a> </li> {% endif %} {% for page in paginator.page_range %} <li {% if page == page_obj.number %} class="page-item active" {% endif %}><a class="page-link" href="?page={{ page }}">{{ page }}</a></li> {% endfor %} {% if page_obj.has_next %} <li class="page-item"> <a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next"> <span aria-hidden="true">&raquo;</span> <span class="sr-only">Next</span> </a> </li> {% endif %} </ul> </nav> </div> {% endblock %}

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

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

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

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

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

quickquip

2021/01/30 04:01 編集

質問(というか何がわからないことなのか)が書かれていないようです。
taro__

2021/01/30 04:11 編集

言葉足らずですみません。 型を合わせて計算する方法がわかりません。 データベースの集計した値を avg_amount = Money.objects.aggregate(Sum('amount'))['amount__sum']/3 と代入したのですが、TypeError: unsupported operand type(s) for /: 'NoneType' and 'int' とエラーが出ました。 avg_amount = int(Money.objects.aggregate(Sum('amount'))['amount__sum'])/3 とすれば、型を合わせることができるのではないかと思い、実行してみました。 しかし、解決しなかったため、質問させていただきました。 初歩的な質問かもしれませんが、解決策をご教授していただけないでしょうか。 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
quickquip

2021/01/30 04:19

情報はこの欄ではなくて質問に書いてください(ここは"質問への追記・修正の依頼"欄です)
taro__

2021/01/30 04:32

すみません。 先程修正させていただきました。 avg_amount = Money.objects.aggregate(Sum('amount'))['amount__sum']はNoneとありますが、代入した変数にはなにも入っていないのでしょうか。 私はint()をつければ、解決するのではないかと考えましたが、それは違うのでしょうか。 None となるときの考慮についてご教授いただけないでしょうか。
guest

回答2

0

まず、試した限りでは、admin画面で、「Taro, Koki Kaze」の3名全員分のデータを1つ以上作成した場合、
エラーなく表示されました。

逆にいうと、上記3名のうち1人でもデータがない場合は、上記及び類似のエラーが出ます。

たとえば、3人に1つずつ、計3件のデータを用意して、表示された画面から、taroを削除して保存ボタンを押した瞬間、
unsupported operand type(s) for -: 'float' and 'NoneType' エラーが出ます。

このとき、 各変数は以下のようになっています。

'pay_kaze': 450, 'pay_koki': 200, 'pay_taro': None,

そして

deficiency_taro = avg_amount - pay_taro

この部分で、avg_amount(2人分の平均)からNoneを減算しようとしているため、上記エラーが発生します。

したがって、データがない場合、Noneではなく、数が入るようにする必要があります。

対策として、たとえばTaroのデータが不存在のとき、現状は
money\money\views.py

pay_taro = Money.objects.filter(name='Taro').aggregate(Sum('amount'))['amount__sum']

がNoneになってしまっています。
これをNoneではなく、ゼロが返ってくるようにすればエラーはなくなります。

例:total_amount及びpay_(個人名)に対して、or 0をつけて、agregateの計算結果がNoneの場合はゼロが代入されるようにする。
money\money\views.py

(略) #db aggregate def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) #sum total_amount = Money.objects.aggregate(Sum('amount'))['amount__sum'] or 0 context["total_amount"] = total_amount #average avg_amount = total_amount/3 context["avg_amount"] = avg_amount #payment/per name=Taro pay_taro = Money.objects.filter(name='Taro').aggregate(Sum('amount'))['amount__sum'] or 0 context["pay_taro"] = pay_taro #payment/per name=Koki pay_koki = Money.objects.filter(name='Koki').aggregate(Sum('amount'))['amount__sum'] or 0 context["pay_koki"] = pay_koki #payment/per name=Kaze pay_kaze = Money.objects.filter(name='Kaze').aggregate(Sum('amount'))['amount__sum'] or 0 context["pay_kaze"] = pay_kaze

ただしこれは応急対策であって、deficiencyおよび全容がどういう仕様なのか明らかにしていただかないと、正しい答えは導けないと思います。
(計算対象のうち、払っていない人(データ上不存在の人)に対しても、deficiencyを計算するのか。
たとえば上記でゼロを返した場合 deficiency_taro は残り二人のpayの平均値に-1をかけた数字になるが、これは仕様として正しいのか
そもそもデータが不存在の人があることを想定していないのか、等)

投稿2021/01/30 05:35

編集2021/01/30 05:55
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

Money.objects.aggregate(Sum('amount'))['amount__sum']の結果がNoneだからです。(Moneyのデータが存在しない)

Noneを3で割るとエラーになるので結果がNoneとなるときの考慮が必要だと思います。

投稿2021/01/30 04:12

errormaker74

総合スコア230

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

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

taro__

2021/01/30 04:16 編集

返信ありがとうございます。 None となるときの考慮についてご教授いただけないでしょうか。
errormaker74

2021/01/30 04:36

> None となるときの考慮についてご教授いただけないでしょうか。 どのようなプログラムを作りたいかによるのであなたの考える仕様次第です。 あなたのプログラムの仕様を知らないので思いつくまま書くとすると… ・Noneの際、context["avg_amount"]に初期値のようなもの(たとえば0)を入れてしまう ・context["avg_amount"]にあえてNoneを入れて、フロントエンドでの表示のときに表示できないことを示す文字列などを表示する などでしょうか。 Noneかどうかは下記のやり方で判定できます。 ``` if avg_amount is None: # Noneのとき pass else: # Noneでないとき pass ``` あなたが作りたい仕様にすればよいと思います。
taro__

2021/01/30 06:31 編集

画像を用いて質問したかったため、質問に追記させていただきました。 上記のように金額の数値を動的に処理するプログラムを実行したいと思い、 avg_amount = Money.objects.aggregate(Sum('amount'))['amount__sum']/3 context["avg_amount"] = avg_amount とviews.py で実行し、htmlファイルで <p>{{ avg_amount|floatformat:1 }}円</p> と実行したところ、画像のように表示できたのですが、テストコードでエラーが発生しました。 この場合初期値は入力できないのではないかと思い、解決策が見つかりません。 解決策をご教授いただけないでしょうか。
errormaker74

2021/01/30 06:11

> テストコードでエラーが発生しました。 'Taro', 'Koki', 'Kaze'や`… / 3`という風にハードコーディングしてしまっているので 逆に「Taro, Koki Kaze」などのデータが前提である仕様にしてもいいかもしれませんね。 テストコードに`Money.objects.create(xx=yy,…)`などのように記載することでテスト時にはデータが作成されてから処理が走るようにしてもいいかもしれません。 理解が進んでから少しずつなおせばいいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問