Python | Django | モデルを用いたテーブル間の紐づけにおけるmany-to-manyの使い方

2021年7月3日

公開日:2021/7/3

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

前記事にて,「モデルを用いたテーブル間の紐づけにおけるone-to-oneの使い方」を記した.前記事での設定をそのまま引き継いだ上で,本記事では,「モデルを用いたテーブル間の紐づけにおけるmany-to-manyの使い方」を以下2構成にて記す.

  1. テーブルの追加方法
  2. データベース(DB)へ値の追加方法

◆実施環境

Python 3.8.8
Django 3.2.3

■モデルを用いたテーブル間の紐づけにおけるmany-to-manyの使い方

  1. テーブルの追加方法

“model_app/models.py"に新たなclass(“Musics", “Musicians")を追加する.追加したコードに"ManyToManyField"を利用した.なお,"models.py"の更新後の内容は以下になる.

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}'

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'


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'

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'


VS Codeの"View"からTerminal(ターミナル)を開き,”conda activate 仮想環境名”を実行し,仮想環境(私の場合,"djangoenv")に移行する.プロジェクト名”model_project”のディレクトリで,以下のように”python manage.py makemigrations –name add_music_musician”を実行すると,以下が出力される.

(djangoenv) C:\Users\shiro\Desktop\210517_python development\mymodeltest\model_project
>python manage.py makemigrations --name add_music_musician # 入力箇所

Migrations for 'model_app': # 以下出力箇所
  model_app\migrations\0004_add_music_musician.py
    - Create model Musics
    - Create model Musicians

”model_app/migrations”には以下のように"0004_add_music_musician.py"が作成される.

続けて,”model_project”のディレクトリで,以下のように”python manage.py migrate model_app”を実行すると,以下が出力される."0004_add_musician_music.py"が適用された.

(djangoenv) C:\Users\shiro\Desktop\210517_17_python development\mymodeltest\modelpjepython develop_project
>python manage.py migrate model_app # 入力箇所

Operations to perform: 以下出力箇所
  Apply all migrations: model_app
Running migrations:
  Applying model_app.0004_add_music_musician... OK

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

  1. データベース(DB)へ値の追加方法

”model_project”に以下のように"manytomany.val.py"を作成する.

”model_project/manytomany.val.py"を以下のように編集する.Table “musics", “musicians", “musicians_musics"に値を入れるコードを記述している.

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

from django import setup
setup()

from model_app.models import Musicians, Musics

def adding_musics():
music1 = Musics(name='Tokyo Gird')
music2 = Musics(name='Love Me Do')
music3 = Musics(name='Viva la Vida')
music4 = Musics(name='Life Is a Flower')
music5 = Musics(name='She Loves You')
music1.save()
music2.save()
music3.save()
music4.save()
music5.save()

def adding_musicians():
musician1 = Musicians(name='Ace of Base')
musician2 = Musicians(name='The Beatles')
musician3 = Musicians(name='ColdPlay')
musician1.save()
musician2.save()
musician3.save()

adding_musics() # musicsに値を追加
adding_musicians() # musicianに値を追加

musician1 = Musicians.objects.get(pk=1)
music1 = Musics.objects.get(pk=1)
music4 = Musics.objects.get(pk=4)

musician2 = Musicians.objects.get(pk=2)
music2 = Musics.objects.get(pk=2)
music5 = Musics.objects.get(pk=5)

musician3 = Musicians.objects.get(pk=3)
music3 = Musics.objects.get(pk=3)

musician1.musics.add(music1, music4) # musicians_musicsに値を追加
musician2.musics.add(music2, music5)
musician3.musics.add(music3)

“manytomany.val.py"で右クリックをすると,以下コマンドが現れるので,"Run Python File in Terminal"をクリックする.DBに値が追加される.

“SQLITE EXPLORER"を開き,各Tableを右クリックをして,"Show Table"をクリックすると以下を確認できる.

“musicians"には以下値が格納されている.

“musics"には以下値が格納されている.

“musicians_musics"には以下値が格納されている.

”model_project/manytomany.val.py"の以下(a)を削除し,(b)を追記する.

(a)
adding_musics()
adding_musicians()
musician1.musics.add(music1, music4)
musician2.musics.add(music2, music5)
musician3.musics.add(music3)

(b)
print(musician1.musics.all())
print(musician2.musics.all())
print(musician3.musics.all())

その後,"manytomany.val.py"で右クリックをし,"Run Python File in Terminal"をクリックすると,以下が出力される."musician1″, “musician2", “musician3″各々に紐づけられている"music"の一覧が以下のように出力される.

<QuerySet [<Musics: Tokyo Gird>, <Musics: Life Is a Flower>]> # musician1と紐づくmusic
<QuerySet [<Musics: Love Me Do>, <Musics: She Loves You>]> # musician2と紐づくmusic
<QuerySet [<Musics: Viva la Vida>]> # musician3と紐づくmusic

■参照

https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/

以上