Python | Django | モデルを用いたテーブル間の紐づけにおけるmany-to-manyの使い方
公開日:2021/7/3
Pythonには,DjangoというWebアプリケーションフレームワークがある.フレームワークのため,Djangoを利用するとWebアプリを通常よりも短時間で開発することが可能になる.
前記事にて,「モデルを用いたテーブル間の紐づけにおけるone-to-oneの使い方」を記した.前記事での設定をそのまま引き継いだ上で,本記事では,「モデルを用いたテーブル間の紐づけにおけるmany-to-manyの使い方」を以下2構成にて記す.
◆実施環境
Python 3.8.8
Django 3.2.3
■モデルを用いたテーブル間の紐づけにおけるmany-to-manyの使い方
“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")を以下赤枠にて確認できる.
”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/
以上