Make組ブログスマートフォン用の表示で見るMake組ブログPython、Webサービスや製品開発、ライブラリー開発についてhirokikyが書きます2013-02-19Djangoで売上を集計/集約処理するDjangoで売上を集計/集約処理する集計/集約します。(この記事ではaggregationを「集計」と訳します。documentationちなみにDjangoでaggregationの機能が追加されたのは1.1からですね。上記のドキュメント読めば集計処理の大体は網羅できると思います。今回はユースケースにあわせて、集計の機能を紹介します。折れ線グラフの算出をやってみます。これくらいの項目があれば十分ですかね。お店の売れ行きや人気商品は掴めると思います。今回考えてみるのはお人形屋さんです。とあるお人形屋さんの売上情報をもとに、集計処理を行なって行きましょう。想定するデータ構造はじめにテーブル/Djangoのモデルからみていきましょう。必要なモデルは2つで、お店に並ぶ商品と売上情報です。models.pyは以下のようになると思います。models.DateTimeField(u"販売日時")こんなところかと。集計をしていきましょう。note今回は省きますが、Itemには他にも商品のカテゴリや販売元などのフィールドが追加できると考えられますね。みることができちゃうと思います。簡単なところから、売上合計金額と件数です。集計の対象期間は「今月」として話をすすめます。今月の初日から昨日までが対象です。その期間内のSalesHistoryを取得してみましょう。today))こんなところと思います。当日のdate、relativedeltaを使って月の初日(first_of_thismonth)をとりました。最後の行でSalesHistoryをfilterしてます。sales_of_thismonth.aggregate(Sum('item__price'))簡単ですね。aggregateを使います。lookupはSum。sales_of_thismonth.values('user').annotate(total_price=Sum('item__price'))商品ごとなりユーザごとの合計金額を求めて、アプリ側で各々の金額を全部の合計金額で割れば比率はでますね。JSライブラリはそのまま値で渡せばよしなにやってくれます。この例では「商品ごと」というなんともビミョーな円グラフですが、応用すれば「商品のカテゴリごと」などもできますね。sales_of_thismonth.values('item').annotate(numof_sales=Count('id')).order_by('-numof_sales')さきほどの円グラフの算出にそのままorder_byをつけただけです。‘-'を付けてるのは降順にするためです。折れ線グラフというのは横軸に日時、縦軸に売上金額(もしくは件数)をとったものを考えます。日付はある単位ごとにまとめたものになりますね。日毎の売上、月毎の売上などです。1年間の売上推移を見るのに日毎の集計をしちゃったら、横に365点とることになるんで非常に見難いですよね。sold_datetime)'}).values('sold_month').annotate(total_price=Sum('item__price'))extraで、values-annotateのグループ化に使う値を作ってあげてます。日毎の集計ならstrftimeじゃなくてdateでもいけそう。おわりに意外とあっさりできましたが、理解するのはちょっとややこしいかも。annotateの前にvaluesをおいてグループ化してやってるわけですが、SQL脳でみると.group_byなどのメソッドが欲しいなというところ。これについては何度も議題にあがってるようです。https://groups.google.com/d/topic/django-developers/dUlwp9z9gGI/discussionよりORMらしい方法(values-annotateのことかな)が採択されたとのこと。ようで、このチケットは「ORMで集計できるようにしよう」という提案のようですね。見てみたところ、もともとの提案ではgroup_byなどであったようですが、まぁ時間のあるときにでもじっくり見ときましょ。Pythonのリストはイテレーターでない。アーカイブPyQという製品を作っていますスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。