Python | Django | モデルを用いた様々なテーブルからの値の取得方法

2021年7月4日

公開日:2021/7/4

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

前記事にて,「モデルを用いたテーブル間の紐づけにおけるmany-to-manyの使い方」を記した.前記事での設定をそのまま引き継いだ上で,本記事では,「モデルを用いた様々なテーブルからの値の取得方法」を以下にて記す.

なお,以下(1)~(3)は,2021/7/1~3に作成している.以下(1)では"many-to-one relationships"(多対1),(2)では"one-to-one relationships"(1対1),(3)では"many-to-many relationships"(多対多)を利用している.

(1) モデルを用いたテーブル間の紐づけにおけるon_delete optionの使い方
(2) モデルを用いたテーブル間の紐づけにおけるone-to-oneの使い方
(3) モデルを用いたテーブル間の紐づけにおけるmany-to-manyの使い方

上記(1)~(3)を利用し,以下1~4の構成にて本記事を記す.

  1. 準備
  2. “many-to-one relationships"(多対1)における値の取得方法
  3. “one-to-one relationships"(多対1)における値の取得方法
  4. “many-to-many relationships"(多対1)における値の取得方法

◆実施環境

Python 3.8.8
Django 3.2.3

■モデルを用いた様々なテーブルからの値の取得方法

  1. 準備

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

“model_app/models.py"に記載されている内容は以下になる."models.py"に"many-to-one relationships"(多対1),"one-to-one relationships"(1対1),"many-to-many relationships"(多対多)が記載されている.

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'
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'
  1. “many-to-one relationships"(多対1)における値の取得方法

“model_app/models.py"において,"ForeignKey"が含まれているクラスの場合,「クラスインスタンス名.フィールド名」を利用し,"ForeignKey"が含まれていないクラスの場合,「クラスインスタンス名.フィールド名_set.all()」を利用する.

なお,"extract_val.py"は以下のように編集する.

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

from django import setup
setup()

from model_app.models import Dorayakis, Shops, Cities

# 1の処理(first:テーブルの1番最初の値)
s1 = Shops.objects.first()
print(s1)

# 2の処理
print(type(s1))

# 3の処理
print(dir(s1))

# 4の処理(last:テーブルの1番最後の値)
s2 = Shops.objects.last()
print(s2)

# 5の処理(all:テーブルのすべての値)
s3 = Shops.objects.all()
print(s3)

# 6の処理
print(s1.city.name)

# 7の処理(s1に接続するdorayakisの値をすべて出力)
print(s1.dorayakis_set.all())

# 8の処理
print(type(s1.dorayakis_set))

# 9の処理
print(dir(s1.dorayakis_set))

■実行結果

# 3の結果より,以下を注目すると関わるテーブルが1なのか多なのかが分かる.

'city’: 1を意味している.
'dorayakis_set’: 多を意味している.

# 1の結果
Shops object (4)

# 2の結果
<class 'model_app.models.Shops'>

# 3の結果
['DoesNotExist', 'MultipleObjectsReturned', '__class__', 
'__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__getstate__', 
'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', 
'__lt__', '__module__', '__ne__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__setstate__', 
'__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
'_check_column_name_clashes', 
'_check_constraints', '_check_default_pk', '_check_field_name_clashes', 
'_check_fields', '_check_id_field', '_check_index_together', 
'_check_indexes', '_check_local_fields', '_check_long_column_names', 
'_check_m2m_through_same_relationship', '_check_managers', '_check_model', 
'_check_model_name_db_lookup_clashes', '_check_ordering', 
'_check_property_name_related_field_accessor_clashes', 
'_check_single_primary_key', '_check_swappable', '_check_unique_together', 
'_do_insert', '_do_update', '_get_FIELD_display', '_get_expr_references', 
'_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', 
'_get_pk_val', '_get_unique_checks', '_meta', '_perform_date_checks', 
'_perform_unique_checks', '_prepare_related_fields_for_save', 
'_save_parents', '_save_table', '_set_pk_val', '_state', 'check', 'city', 
'city_id', 'clean', 'clean_fields', 'date_error_message', 'delete', 
'dorayakis_set', 'from_db', 'full_clean', 'get_deferred_fields', 'id', 
'name', 'objects', 'pk', 'prepare_database_save', 'refresh_from_db', 
'save', 'save_base', 'serializable_value', 'unique_error_message', 
'validate_unique']

# 4の結果
Shops object (6)

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

# 6の結果
北区

# 7の結果
<QuerySet [<Dorayakis: Dorayakis object (10)>, 
<Dorayakis: Dorayakis object (11)>, 
<Dorayakis: Dorayakis object (12)>]>

# 8の結果
<class 'django.db.models.fields.related_descriptors.
create_reverse_many_to_one_manager.<locals>.RelatedManager'>

# 9の結果
['__call__', '__class__', '__class_getitem__', '__delattr__', '__dict__', 
'__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', 
'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', 
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__setattr__', '__sizeof__', '__slotnames__', '__str__', 
'__subclasshook__', '__weakref__', '_apply_rel_filters', 
'_constructor_args', '_db', '_get_queryset_methods', '_hints', 
'_insert', '_queryset_class', '_remove_prefetched_objects', 
'_set_creation_counter', '_update', 'add', 'aggregate', 'alias', 'all', 
'annotate', 'auto_created', 'bulk_create', 'bulk_update', 'check', 
'complex_filter', 'contribute_to_class', 'core_filters', 'count', 
'create', 'creation_counter', 'dates', 'datetimes', 'db', 'db_manager', 
'deconstruct', 'defer', 'difference', 'distinct', 
'do_not_call_in_templates', 'earliest', 'exclude', 'exists', 'explain', 
'extra', 'field', 'filter', 'first', 'from_queryset', 'get', 
'get_or_create', 'get_prefetch_queryset', 'get_queryset', 'in_bulk', 
'instance', 'intersection', 'iterator', 'last', 'latest', 'model', 'name', 
'none', 'only', 'order_by', 'prefetch_related', 'raw', 'reverse', 
'select_for_update', 'select_related', 'set', 'union', 'update', 
'update_or_create', 'use_in_migrations', 'using', 'values', 'values_list']
  1. “one-to-one relationships"(1対1)における値の取得方法

“model_app/models.py"において,どちらのクラスでも,「クラスインスタンス名.フィールド名」を利用する.

なお,"extract_val.py"は以下のように編集する.

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

from django import setup
setup()

from model_app.models import Places, Companies

# 1の処理(first:テーブルの1番最初の値)
p1 = Places.objects.first()
print(p1)

# 2の処理
print(type(p1))

# 3の処理
print(dir(p1))

# 4の処理
print(p1.name)

# 5の処理
print(p1.companies.name)

# 6の処理
c1 = Companies.objects.last()
print(c1.name)

■実行結果

# 1の結果
Places object (1)

# 2の結果
<class 'model_app.models.Places'>

# 3の結果
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', 
'__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 
'__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', 
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', 
'__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
'_check_column_name_clashes', '_check_constraints', '_check_default_pk', 
'_check_field_name_clashes', '_check_fields', '_check_id_field', 
'_check_index_together', '_check_indexes', '_check_local_fields', 
'_check_long_column_names', '_check_m2m_through_same_relationship', 
'_check_managers', '_check_model', '_check_model_name_db_lookup_clashes', 
'_check_ordering', '_check_property_name_related_field_accessor_clashes', 
'_check_single_primary_key', '_check_swappable', '_check_unique_together', 
'_do_insert', '_do_update', '_get_FIELD_display', '_get_expr_references', 
'_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', 
'_get_pk_val', '_get_unique_checks', '_meta', '_perform_date_checks', 
'_perform_unique_checks', '_prepare_related_fields_for_save', 
'_save_parents', '_save_table', '_set_pk_val', '_state', 'address', 
'check', 'clean', 'clean_fields', 'companies', 'date_error_message', 
'delete', 'from_db', 'full_clean', 'get_deferred_fields', 'id', 'name', 
'objects', 'pk', 'prepare_database_save', 'refresh_from_db', 'save', 
save_base', 'serializable_value', 'unique_error_message', 'validate_unique']

# 4の結果
Kawasaki

# 5の結果
JFE Steel

# 6の結果
KOBE Steel
  1. “many-to-many relationships"(多対多)における値の取得方法

“model_app/models.py"において,"ManyToMany"が含まれているクラスの場合,「クラスインスタンス名.フィールド名」を利用し,"ManyToMany"が含まれていないクラスの場合,「クラスインスタンス名.フィールド名_set.all()」を利用する.

なお,"extract_val.py"は以下のように編集する.

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

from django import setup
setup()

from model_app.models import Musics, Musicians

# 1の処理
m_cs = Musicians.objects.first()
print(m_cs.musics.all())

# 2の処理
print(type(m_cs))

# 3の処理
print(dir(m_cs))

# 4の処理
m_ans = Musics.objects.first()
print(m_ans.musicians_set.all())

■実行結果

# 1の結果
<QuerySet [<Musics: Tokyo Gird>, <Musics: Life Is a Flower>]>

# 2の結果
<class 'model_app.models.Musicians'>

# 3の結果
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', 
'__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 
'__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', 
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', 
'__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
'_check_column_name_clashes', '_check_constraints', '_check_default_pk', 
'_check_field_name_clashes', '_check_fields', '_check_id_field', 
'_check_index_together', '_check_indexes', '_check_local_fields', 
'_check_long_column_names', '_check_m2m_through_same_relationship', 
'_check_managers', '_check_model', '_check_model_name_db_lookup_clashes', 
'_check_ordering', '_check_property_name_related_field_accessor_clashes', 
'_check_single_primary_key', '_check_swappable', '_check_unique_together', 
'_do_insert', '_do_update', '_get_FIELD_display', '_get_expr_references', 
'_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', 
'_get_pk_val', '_get_unique_checks', '_meta', '_perform_date_checks', 
'_perform_unique_checks', '_prepare_related_fields_for_save', '_save_parents', 
'_save_table', '_set_pk_val', '_state', 'check', 'clean', 'clean_fields', 
'date_error_message', 'delete', 'from_db', 'full_clean', 'get_deferred_fields', 
'id', 'musics', 'name', 'objects', 'pk', 'prepare_database_save', 
'refresh_from_db', 'save', 'save_base', 'serializable_value', 
'unique_error_message', 'validate_unique'] 

# 4の結果
<QuerySet [<Musicians: Ace of Base>]>

以上