見出し画像

DjangoのORMを使って集計方法を学ぶレシピ

この技術ノートではDjangoORMを用いたデータの集計方法を学ぶことができます。

Djangoが提供する以下のメソッドを使ってとあるECショップの商品の販売データを集計するという事例で具体的に解説していきます。

実際にデモデータの環境を準備して操作しながら学ぶことができる内容になっています。

DjangoのORMで提供される基本的なメソッドについては以下の記事で学習することができますので、こちらも確認してみてください。


1.事前準備

ORMの各メソッドの動作を確認するための環境の準備を行います。

動作確認用のDjangoプロジェクトと初期データを準備したGitリポジトリを用意してありますので、以下の手順で環境を準備しましょう。

まず、任意のディレクトリ上で以下のコマンドを実行してリポジトリをクローンします。

git clone https://github.com/sinjorjob/django-aggregate.git
cd django-aggregate

仮想環境を作成してアクティベートし、必要なモジュールをインストールします。

python -m venv env
env\scripts\activate
pip install django PyYAML

マイグレーションを実行します。

python manage.py makemigrations
python manage.py migrate

管理者ユーザを作成します。

python manage.py createsuperuser

以下のコマンドを実行して、動作確認用のデモデータをインポートします。

python manage.py loaddata --format=yaml ec_site/fixtures/sample_data.yaml

以下のコマンドを実行して開発サーバを起動したらhttp://127.0.0.1:8000/adminにアクセスして管理者ユーザでログオンします。

python manage.py runserver

以上で環境準備は完了です。

2.テーブル構成について

今回利用するテーブル構成について簡単に解説します。

まずは、ec_site\models.pyを参照してください。
以下のようなモデルが定義されています。

from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
    class Meta:
        verbose_name = 'カテゴリ'
        verbose_name_plural = "カテゴリ"
    name = models.CharField(max_length=100)
    def __str__(self):
        return self.name
class Product(models.Model):
    class Meta:
        verbose_name = '商品'
        verbose_name_plural = "商品"
    name = models.CharField(verbose_name = '製品名', max_length=150, null = False, blank=False)
    price = models.IntegerField(verbose_name = '価格')
    category = models.ForeignKey(Category, on_delete = models.PROTECT,verbose_name ="カテゴリ")
    def __str__(self):
        return self.name
class OrderItem(models.Model):
    class Meta:
        verbose_name = '注文データ'
        verbose_name_plural = '注文データ'
    user = models.ForeignKey(User,verbose_name = 'ユーザ',on_delete = models.CASCADE, null=True)
    items = models.ManyToManyField('Product', related_name='order', blank=True)
    created_date = models.DateField(auto_now_add=True)
    price = models.DecimalField(verbose_name="合計金額",max_digits=7, decimal_places=0, null=True, blank=True)
    name = models.CharField(verbose_name="氏名", max_length=50, blank=True)
    def __str__(self):
        return f'注文日: {self.created_date.strftime("%b %d %Y %I:%M %p")}'
class OrderItemDetail(models.Model):
    class Meta:
        verbose_name = '注文明細'
        verbose_name_plural = '注文明細'
    invoice = models.ForeignKey(OrderItem, on_delete=models.CASCADE)
    product = models.ForeignKey(Product,verbose_name='商品',on_delete=models.CASCADE)
    quantity = models.IntegerField(verbose_name='数量')

以下の4つのテーブルを定義しています。

通常のショップサイトでは、1回の注文で複数の商品を複数個購入することができます。
そのようなテーブル構造にするため、1つの注文データ(OrderItem)に対して複数の商品(Product)が紐づき、複数の明細テーブル(OrderItemDetail)が紐づくようなテーブル構成になっています。
また、製品(Product)に対しては1つカテゴリを割り当てる構成にしています。

adminサイト(http://127.0.0.1:8000/admin)にアクセスして、実際のサンプルデータを確認してみましょう。

商品テーブルをクリックすると、下図のように商品名の情報が登録されていることが確認できます。

注文テーブルをクリックすると、18件の注文データが登録されていることが確認できます。

また、注文テーブルをクリックすると下図のように複数の注文明細データが表示されます。

注文明細テーブルをクリックすると下図のように明細データが表示されます。

それでは、次から実際に注文データの分析を始めていきます。

3.各テーブルのレコード数をチェック

まずは、各テーブルのレコード数をチェックしてみましょう。

まず、以下のコマンドを実行してDjangoのシェルモードを起動します。

python manage.py shell

これから扱うモデルクラスをインポートします。

from ec_site.models import *

それでは、countメソッドを使ってCategory、Product、OrderItem、OrderItemDetailのレコード数をチェックしてみましょう。

>>> Category.objects.count()
3
>>> Product.objects.count()
9
>>> OrderItem.objects.count()
18
>>> OrderItemDetail.objects.count()
24

上記の通り、カテゴリは3件、製品は9件、注文データは18件、注文の明細データは24件のデータが存在していることが確認できます。

4.全期間の全商品の売上合計金額を求める

まずは注文データ(OrderItem)からすべての売上金額(price)の合計を求めます。

ここから先は

9,183字 / 2画像

¥ 500

主にITテクノロジー系に興味があります。 【現在興味があるもの】 python、Django,統計学、機械学習、ディープラーニングなど。 技術系ブログもやってます。 https://sinyblog.com/