Python | Django | モデルを用いたForeignKey関連のデータ取得方法

2021年7月5日

公開日:2021/7/5

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

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

  1. 準備
  2. データ取得方法

◆実施環境

Python 3.8.8
Django 3.2.3

■モデルを用いたForeignKey関連のデータ取得方法

  1. 準備

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

“model_app/models.py"に記載されている内容は以下になる."models.py"の"many-to-one relationships"(多対1)を主に利用していく.

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. データ取得方法

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

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

from django import setup
setup()

from model_app.models import Dorayakis, Shops

# 1の処理(all利用)
for dorayaki in Dorayakis.objects.all():
  print(dorayaki.id, dorayaki.name, dorayaki.shop.name, dorayaki.shop.city.name)

# 2の処理(shop_name='うさぎや'でfilter)
for dorayaki in Dorayakis.objects.filter(shop__name='うさぎや').all():
  print(dorayaki.id, dorayaki.name, dorayaki.shop.name, dorayaki.shop.city.name)

# 3の処理(shop_name='亀十'でexclude)
for dorayaki in Dorayakis.objects.exclude(shop__name='亀十').all():
  print(dorayaki.id, dorayaki.name, dorayaki.shop.name, dorayaki.shop.city.name)

# 4の処理
print(Shops.objects.filter(dorayakis__name='こしあんどら焼き').all())

# 5の処理(order_byの利用)
for dorayaki in Dorayakis.objects.order_by('-shop__id').all():
  print(dorayaki.id, dorayaki.name, dorayaki.shop.id, dorayaki.shop.name)

# 6の処理(group_byの利用)
from django.db.models import Max, Min
print(Dorayakis.objects.values('name').annotate(Max('shop_id'),Min('shop_id')))

■実行結果

# 1の結果
10 つぶあんどら焼き うさぎや 北区
11 こしあんどら焼き うさぎや 北区
12 クリームどら焼き うさぎや 北区
13 つぶあんどら焼き 亀十 北区
14 こしあんどら焼き 亀十 北区
15 クリームどら焼き 亀十 北区
16 つぶあんどら焼き 草月 北区
17 こしあんどら焼き 草月 北区
18 クリームどら焼き 草月 北区

# 2の結果
10 つぶあんどら焼き うさぎや 北区
11 こしあんどら焼き うさぎや 北区
12 クリームどら焼き うさぎや 北区

# 3の結果
10 つぶあんどら焼き うさぎや 北区
11 こしあんどら焼き うさぎや 北区
12 クリームどら焼き うさぎや 北区
16 つぶあんどら焼き 草月 北区
17 こしあんどら焼き 草月 北区
18 クリームどら焼き 草月 北区

# 4の結果
<QuerySet 
[<Shops: Shops object (4)>, <Shops: Shops object (5)>, 
<Shops: Shops object (6)>]>

# 5の結果
18 クリームどら焼き 6 草月
17 こしあんどら焼き 6 草月
16 つぶあんどら焼き 6 草月
15 クリームどら焼き 5 亀十
14 こしあんどら焼き 5 亀十
13 つぶあんどら焼き 5 亀十
12 クリームどら焼き 4 うさぎや
11 こしあんどら焼き 4 うさぎや
10 つぶあんどら焼き 4 うさぎや

# 6の結果
<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}]>

以上