Python | Django | モデルを用いたデータベースからのデータ取得方法およびデータ集計方法

2021年7月5日

公開日:2021/7/5

Pythonには,DjangoというWebアプリケーションフレームワークがある.フレームワークのため,Djangoを利用するとWebアプリを通常よりも短時間で開発することが可能になる.

前記事にて,「モデルを用いた様々なテーブルからの値の取得方法」を記した.前記事での設定をそのまま引き継いだ上で,本記事では,「モデルを用いたデータベースからのデータ取得方法およびデータ集計方法」を以下にて記す.

なお,2021/6/29に「モデルを用いたデータベースからのデータ取得方法」の記事を作成している.本記事である「モデルを用いたデータベースからのデータ取得方法およびデータ集計方法」では,前回(6/29)よりも詳細なデータ取得方法や集計方法を記す.

  1. 準備
  2. データ取得方法
    (1) AND条件・OR条件
    (2) contain(部分一致)
    (3) exclude(除外)
    (4) order_by(並び替え)
    (5) count(数を数える)
  3. 基本的なデータ集計方法
  4. GROUP BYでのデータ集計方法

◆実施環境

Python 3.8.8
Django 3.2.3

■モデルを用いたデータベースからのデータ取得方法およびデータ集計方法

  1. 準備

“model_project"に"query_process.py"を以下のように作成する.

“model_app/models.py"に記載されている内容は以下になる."models.py"の"many-to-one relationships"(多対1)を主に利用していく.そのため,以下45~46行目にコードを追加した.

from django.db import models
from django.utils import timezone

class
Date(models.Model):
# 抽象基底クラス
  create_date = models.DateTimeField(default=timezone.now)
  update_date = models.DateTimeField(default=timezone.now)
class
Meta:
    abstract =
True
class
Cake(Date):
  cake_name = models.CharField(max_length=40)
  birthplace = models.CharField(max_length=40)
  birthday = models.DateField(default='1900-01-01')
  inventor = models.CharField(max_length=40)
  sales_amounts = models.IntegerField()
  like = models.BooleanField(default=True)
  email = models.EmailField(db_index=True)
  web_site = models.URLField()
  feed_back = models.TextField(null=True,blank=True)
class
Meta:
    db_table =
'cake'
    index_together =
[['cake_name','inventor']]
    ordering =
['birthday']
def
__str__(self):
return
f'{self.cake_name}'
# 以下"many-to-one relationships"の記載
class
Dorayakis(models.Model):
  name = models.CharField(max_length=30)
  price = models.IntegerField()
  birthday = models.DateField(default='1900-01-01')
  shop = models.ForeignKey(
'Shops', on_delete=models.RESTRICT
  )
  city = models.ForeignKey(
'Cities', on_delete=models.CASCADE
  )
class
Meta:
    db_table =
'dorayakis'

  def __str__(self): # 今回追加箇所
    return f'{self.id},{self.name}' # 今回追加箇所

class
Shops(models.Model):
  name = models.CharField(max_length=30)
  city = models.ForeignKey(
'Cities', on_delete=models.CASCADE
  )
class
Meta:
    db_table =
'shops'
class
Cities(models.Model):
  name = models.CharField(max_length=30)
class
Meta:
    db_table =
'cities'
# 以下"one-to-one relationships"の記載
class
Places(models.Model):
  name = models.CharField(max_length=50)
  address = models.CharField(max_length=80)
class
Meta:
    db_table =
'places'
class
Companies(models.Model):
  place = models.OneToOneField(
    Places,
    on_delete=models.CASCADE,
    primary_key=True
)
  name = models.CharField(max_length=50)
class
Meta:
    db_table =
'companies'
# 以下"many-to-many relationships"の記載
class
Musics(models.Model):
  name = models.CharField(max_length=50)
def
__str__(self):
return self.name

  class
Meta:
    db_table =
'musics'
class
Musicians(models.Model):
  name = models.CharField(max_length=30)
  musics = models.ManyToManyField(Musics)
# ManyToManyFieldの利用
def
__str__(self):
return self.name

  class
Meta:
    db_table =
'musicians'

なお,現時点でのDBに含まれている値を以下に記す.

SQLiteをインストールし(詳細はこちら参照),"SQLITE EXPLORER"を開くと,各Table(“dorayakis", “shops", “cities")を以下赤枠にて確認できる.

上記赤枠のTable"dorayakis"を右クリックをし,"Show Table"をクリックすると,Tableに含まれている値の詳細は以下になる.

上記赤枠のTable"shops"を右クリックをし,"Show Table"をクリックすると,Tableに含まれている値の詳細は以下になる.

上記赤枠のTable"cities"を右クリックをし,"Show Table"をクリックすると,Tableに含まれている値の詳細は以下になる.

  1. データ取得方法

データ取得方法では,以下構成にてデータの取得方法を記す.

(1) AND条件・OR条件
(2) contain(部分一致)
(3) exclude(除外)
(4) order_by(並び替え)
(5) count(数を数える)

(1) AND条件・OR条件

AND条件:複数の条件のいずれにも合致する値を取得する.
OR条件:複数の条件のいずれかに合致する値を取得する.

上記で作成した"query_process.py"を以下のように編集する.

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')

from django import setup
setup()

from model_app.models import Dorayakis

# 1の処理(AND条件を利用したfilter)
print(Dorayakis.objects.filter(name='つぶあんどら焼き',city_id=2).all())

# 2の処理(AND条件を利用したfilter:query詳細確認)
print(Dorayakis.objects.filter(name='つぶあんどら焼き',city_id=2).all().query)

# 3の処理(OR条件を利用したfilter)
from django.db.models import Q
print(Dorayakis.objects.filter(Q(name='こしあんどら焼き') | Q(shop_id=4)).all())

# 4の処理(OR条件を利用したfilter:query詳細確認)
print(Dorayakis.objects.filter(Q(name='こしあんどら焼き') | Q(shop_id=4)).all().query)

■実行結果

# 1の結果
<QuerySet [<Dorayakis: 10,つぶあんどら焼き>, 
<Dorayakis: 13,つぶあんどら焼き>, <Dorayakis: 16,つぶあんどら焼き>]>

# 2の結果
SELECT "dorayakis"."id", "dorayakis"."name", "dorayakis"."price", 
"dorayakis"."birthday", "dorayakis"."shop_id", "dorayakis"."city_id" 
FROM "dorayakis" WHERE 
("dorayakis"."city_id" = 2 AND "dorayakis"."name" = つぶあんどら焼き)

# 3の結果
<QuerySet [<Dorayakis: 10,つぶあんどら焼き>, 
<Dorayakis: 11,こしあんどら焼き>, <Dorayakis: 12,クリームどら焼き>, 
<Dorayakis: 14,こしあんどら焼き>, <Dorayakis: 17,こしあんどら焼き>]>

# 4の結果
SELECT "dorayakis"."id", "dorayakis"."name", "dorayakis"."price", 
"dorayakis"."birthday", "dorayakis"."shop_id", "dorayakis"."city_id" 
FROM "dorayakis" WHERE 
("dorayakis"."name" = こしあんどら焼き OR "dorayakis"."shop_id" = 4)

(2) contain(部分一致)

contain(部分一致):値の一部に合致する値を取得する.

“query_process.py"を以下のように編集する.

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')

from django import setup
setup()

from model_app.models import Dorayakis

# 1の処理(containを利用したfilter)
print(Dorayakis.objects.filter(name__contains='あん').all())

# 1の処理(containを利用したfilter:query詳細確認)
print(Dorayakis.objects.filter(name__contains='あん').all().query)

■実行結果

# 1の結果
<QuerySet [<Dorayakis: 10,つぶあんどら焼き>, 
<Dorayakis: 11,こしあんどら焼き>, <Dorayakis: 13,つぶあんどら焼き>, 
<Dorayakis: 14,こしあんどら焼き>, <Dorayakis: 16,つぶあんどら焼き>, 
<Dorayakis: 17,こしあんどら焼き>]>

# 2の結果
SELECT "dorayakis"."id", "dorayakis"."name", "dorayakis"."price", 
"dorayakis"."birthday", "dorayakis"."shop_id", "dorayakis"."city_id" 
FROM "dorayakis" WHERE "dorayakis"."name" LIKE %あん% ESCAPE '\'

(3) exclude(除外)

exclude(除外):特定の値を除外した値を取得する.

“query_process.py"を以下のように編集する.

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')

from django import setup
setup()

from model_app.models import Dorayakis

# 1の処理(excludeを利用)
print(Dorayakis.objects.exclude(name='つぶあんどら焼き').all())

# 2の処理(excludeを利用:query詳細確認)
print(Dorayakis.objects.exclude(name='つぶあんどら焼き').all().query)

■実行結果

# 1の結果
<QuerySet [<Dorayakis: 11,こしあんどら焼き>, 
<Dorayakis: 12,クリームどら焼き>, <Dorayakis: 14,こしあんどら焼き>, 
<Dorayakis: 15,クリームどら焼き>, <Dorayakis: 17,こしあんどら焼き>, 
<Dorayakis: 18,クリームどら焼き>]>

# 2の結果
SELECT "dorayakis"."id", "dorayakis"."name", "dorayakis"."price", 
"dorayakis"."birthday", "dorayakis"."shop_id", "dorayakis"."city_id" 
FROM "dorayakis" WHERE NOT ("dorayakis"."name" = つぶあんどら焼き)

(4) order_by(並び替え)

order_by(並び替え):特定の並び替えに基づき値を取得する.

“query_process.py"を以下のように編集する.

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')

from django import setup
setup()

from model_app.models import Dorayakis

# 1の処理(order_byを利用)
print(Dorayakis.objects.order_by('-shop_id').all())

# 2の処理(order_byを利用:query詳細確認)
print(Dorayakis.objects.order_by('-shop_id').all().query)

■実行結果

# 1の結果
<QuerySet [<Dorayakis: 18,クリームどら焼き>, 
<Dorayakis: 17,こしあんどら焼き>, <Dorayakis: 16,つぶあんどら焼き>, 
<Dorayakis: 15,クリームどら焼き>, <Dorayakis: 14,こしあんどら焼き>, 
<Dorayakis: 13,つぶあんどら焼き>, <Dorayakis: 12,クリームどら焼き>, 
<Dorayakis: 11,こしあんどら焼き>, <Dorayakis: 10,つぶあんどら焼き>]>

# 2の結果
SELECT "dorayakis"."id", "dorayakis"."name", "dorayakis"."price", 
"dorayakis"."birthday", "dorayakis"."shop_id", "dorayakis"."city_id" 
FROM "dorayakis" ORDER BY "dorayakis"."shop_id" DESC

(5) count(数を数える)

count(数を数える):特定の数を数えて,出力する.

“query_process.py"を以下のように編集する.

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')

from django import setup
setup()

from model_app.models import Dorayakis

# 1の処理(countを利用)
print(Dorayakis.objects.count())

# 2の処理(nameが合致する値についてcountを利用)
print(Dorayakis.objects.filter(name='つぶあんどら焼き').count())

■実行結果

# 1の結果
9

# 2の結果
3
  1. 基本的なデータ集計方法

(1) Count: 数を数える
(2) Max: 最大値を取得する
(3) Min: 最小値を取得する
(4) Avg: 平均値を取得する
(5) Sum: 積算値を取得する

“query_process.py"を以下のように編集する.

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')

from django import setup
setup()

from model_app.models import Dorayakis

# 1の処理
from django.db.models import Count, Max, Min, Avg, Sum
print(Dorayakis.objects.aggregate(
  Count('shop_id'),Max('shop_id'),
  Min('shop_id'),Avg('shop_id'),
  Sum('shop_id'))
  )

# 2の処理
print(Dorayakis.objects.aggregate(
  count_shop_id=Count('shop_id'),
  max_shop_id=Max('shop_id'),
  min_shop_id=Min('shop_id'),
  avg_shop_id=Avg('shop_id'),
  sum_shop_id=Sum('shop_id'))
)

■実行結果

# 1の結果
{'shop_id__count': 9, 'shop_id__max': 6, 'shop_id__min': 4, 
'shop_id__avg': 5.0, 'shop_id__sum': 45}

# 2の結果
{'count_shop_id': 9, 'max_shop_id': 6, 'min_shop_id': 4, 
'avg_shop_id': 5.0, 'sum_shop_id': 45}
  1. GROUP BYでのデータ集計方法

“GROUP BY"は"values"と"annotate"を利用する.以下は名前を集計し,名前ごとに"shop_id"の最大値を出力することを意味している.

「values.('name’).annotate(Max('shop_id’))」

“query_process.py"を以下のように編集する.

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')

from django import setup
setup()

from model_app.models import Dorayakis

from django.db.models import Count, Max, Min, Avg, Sum

# 1の処理
print(Dorayakis.objects.values('name').annotate(
  Max('shop_id'), Min('shop_id')
))

■実行結果

# 1の結果
<QuerySet 
[{'name': 'こしあんどら焼き', 'shop_id__max': 6, 'shop_id__min': 4}, 
{'name': 'つぶあんどら焼き', 'shop_id__max': 6, 'shop_id__min': 4}, 
{'name': 'クリームどら焼き', 'shop_id__max': 6, 'shop_id__min': 4}]>

■参照

https://docs.djangoproject.com/en/3.2/topics/db/aggregation/

以上