質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.49%
Django

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Python

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

Q&A

解決済

1回答

5695閲覧

顧客別、月次別の売上高集計表の作り方

退会済みユーザー

退会済みユーザー

総合スコア0

Django

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Python

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

0グッド

0クリップ

投稿2015/09/09 15:13

編集2015/09/09 15:18

Djangoで作っているアプリの中で、顧客別、月次別の売上高集計表を作成しようと考えています。
表示したい画面は、下記のようなものです。
sample

顧客と売上を扱うモデルは、下記のとおりです。(これ自体はうまく動いています。)

python

1#models.py 2 3class Customer(models.Model): #顧客を扱うmodel 4 id = models.IntegerField('顧客番号', blank = True, primary_key = True, unique = True) 5 name = models.CharField(u'顧客名称', blank = True, max_length = 100) 6 def __unicode__(self): 7 return u"%s" % self.id 8 9class Sales(models.Model): #売上を扱うmodel 10 date = models.DateField(u'売上日') 11 customer_id = models.ForeignKey(Customer) #顧客ID 12 ammount = models.IntegerField(u'金額') 13 def __unicode__(self): 14 return u"%s" % self.customer_id

views.pyをどうしたらよいか分からないのですが、現状、下記のようにしています。

python

1#views.py 2def month_total(request): 3 customer = Customer.objects.all() 4 customerlist = [] #空のリストを作成 5 for customer in customer: 6 customerlist.append(customer.id) #顧客IDのリストを作成 7 8 start_date = date(2012,10,1) #2012年10月1日からのデータを取りまとめます。 9 today = date.today() 10 end_date = date.fromtimestamp(time.mktime((today.year,today.month + 1,1,0,0,0,0,0,0))) #今日を含む月の月末までを集計の対象とします。 11 12 # 各月の初日のリストを取得するためのコード 13 months = [start_date] 14 first_date_of_each_month = start_date 15 while first_date_of_each_month < end_date: 16 first_date_of_each_month = date.fromtimestamp(time.mktime((first_date_of_each_month.year,first_date_of_each_month.month + 1,1,0,0,0,0,0,0))) 17 months.append(first_date_of_each_month) #ここまでで、 [datetime.date(2012, 10, 1), datetime.date(2012, 11, 1), ・・・,, datetime.date(2015, 10, 1)]というリストができます(これ自体はうまくいっています)。 18 19 sales_for_each_customer= [] #顧客毎の売上を入れるための空のリスト 20 21 for customer in customerlist: 22 sales = Sales.objects.filter(customer_id = customer) #各顧客への売上をピックアップ 23 sales_in_each_month = [] #各顧客の各月毎の売上を集計するための空のリスト 24 for m in months : 25 last_date_of_each_month = date.fromtimestamp(time.mktime((m.year,m.month + 1,1,0,0,0,0,0,0))) - timedelta(days=1) #各月の月末の日 26 sales_in_month = 0 #各顧客の各月売上集計 27 for s in sales : 各顧客への売上が、どの月のものかを判定するコード 28 if s.date >= first_date_of_each_month and s.date <= last_date_of_each_month : #もし、当該売上日が当月初日以上当月月末日以下であった場合 29 sales_in_month = sales_in_month + s.ammount #当該売上を当月売上高に集計 30 sales_in_each_month.append(sales_in_month) 31 first_date_of_each_month = last_date_of_each_month + timedelta(days = 1) #次の月の初日 32 sales_for_each_customer.append(sales_in_each_month) #[・・・、(顧客AのH27.1月売上)、(顧客AのH27.2月売上)、・・・]というリストができる。(これ自体はうまくいきます。) 33 first_date_of_each_month = start_date #次の顧客に移る前に、2012年10月1日に戻す。 34 35 return render_to_response('cls/sales_list.html', 36 {''months' : months, 'sales_in_each_month' : sales_in_each_month, 'customerlist' : customerlist, 'sales_for_each_customer' : sales_for_each_customer}, 37 context_instance = RequestContext(request) 38 ) 39

テンプレートは、下記のとおりです。

html

1<!--sales_list.html--> 2{% extends "base.html" %} 3{% load humanize %} 4・・・ 5{% block content %} 6<table> 7<tr> 8 <th>顧客id</th> 9 {% for months in months %} 10 <th>{{months | date:"Y-m"}}</th> 11 {% endfor %} 12</tr> 13{% for customer in customerlist %} 14<tr> 15 <td>{{customer}}</td> 16 {% for sales in sales_for_each_site %} 17 <td style = "text-align:right">{{sales | intcomma}}</td> 18 {% endfor %} 19</tr> 20{% endfor %} 21</table> 22{% endblock %}

上記の結果、sales_for_each_customerには、 [[顧客Aの2012.10月売上, 顧客Aの2012.11月売上,・・・,顧客Aの2015.9月売上],[顧客Bの2012.10月売上, 顧客Bの2012.11月売上,・・・,顧客Bの2015.9月売上],・・・]が入っていることは確認できています。
しかしながら、実際に表示されるのは、顧客Aの2012.10月のところに顧客Aの各月の売上のリストが表示され、顧客Aの2012.11月のところに顧客Bの各月の売上のリストが表示されるようなことになってしまっています。
どうしたら良いのでしょうか。

そもそも、この方法は、足りない知識を使って、何とか無理矢理作ったコードです。しかし、このような処理自体はよくありがちなものではないかと思います。一般的に、こういう時はこういう考え方でやるという定番的な方法があるのであれば、それを知りたいです。

分かりづらい内容の質問を長々と書いて申し訳ありません。
お分かりの方、ご教示頂ければ幸いです。
よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

HTMLにある"sales_for_each_site"がPythonから引き渡された"sales_for_each_customer"であっていますか?
sales_for_each_customerの構造は[[A社の月別売上リスト],[B社の月別売上リスト]...]ですね。
今のソースコードではまず表作成部分のネストが足りていません。
そして顧客IDと売上高が別データになっているので、1つのテーブルにまとめるのがとても大変です。
どうして大変になるのか、以下修正例で示してみます。

◆オリジナルのコード◆
{% for customer in customerlist %}

<tr> <td>{{customer}}</td> {% for sales in sales_for_each_site %}←ここで各社の売上リストを取り出しています。 ##sales = [A社の売上リスト]が取り出される。
<td style = "text-align:right">{{sales | intcomma}}</td> ##salesを表示するので、A社の売上リストが指定されたセルに表示される。 {% endfor %}
</tr> {% endfor %} --------------------------------------------------------------------------------------- ◆ネストを増やしただけのコード◆ ```HTML {% for customer in customerlist %} <tr> <td>{{customer}}</td> {% for sales in sales_for_each_site %} ##sales =[A社の売上リスト]
{% for each_month in sales %}}

##each_month=[各月の売上]

<td style = "text-align:right">{{each_month | intcomma}}</td> {% endfor %} {% endfor %}
</tr> {% endfor %} ``` 上記コードでは1行に全顧客の各月売上がずらっと並び、それが顧客ID分繰り返されます。 なぜこうなるのかと言うと、表の行送りをcustomerのループで制御しているからです。 customerのループは売上データのループと無関係に動きますから、正しいタイミングで 次の顧客ID分のデータ表示を始めることが出来ません。

つまり、顧客IDと顧客ごとの各月売上とで1セットのデータとなっている必要があります。
なので顧客IDと売上で以下のようなリストを作るとよいでしょう。
[['顧客A',[1月の売上,2月の売上,3月の売上...]],['顧客B',[1月の売上,2月の売上,3月の売上...]]]
仮に上記データをsales_for_each_customerとすると、以下HTMLで表を作れます。

HTML

1{% for each_customer in sales_for_each_customer %} 2<tr> 3 <td>{{each_customer.0}}<td> 4 {% for each_month in each_customer.1 %} 5 <td>{{each_month}}</td> 6 {% endfor %} 7</tr> 8{% endfor %} 9コード

コード全体へのアドバイスは差し控えますが、考え方としては顧客IDとその顧客のデータをきちんと
紐づけておくのが大事だと思います。

投稿2015/09/10 17:23

Fuekem

総合スコア19

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

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

退会済みユーザー

退会済みユーザー

2015/09/11 13:28

Fuekemさん、詳しくご説明頂き、ありがとうございました。 無事、解決することができました。 [[顧客A,[1月売上,2月売上,・・・]],[顧客B,[1月売上,2月売上,・・・]],・・・] という感じでリストを作っていけば良いのですね。 forループの内側でもう一回forループを動かすことで、更に深いリストの要素を回すことができるということも分かりました。 リストで処理する場合のコツがよく分かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問