Python | Django | モデルを用いたテーブル間の紐づけにおけるon_delete optionの使い方
公開日:2021/7/1
Pythonには,DjangoというWebアプリケーションフレームワークがある.フレームワークのため,Djangoを利用するとWebアプリを通常よりも短時間で開発することが可能になる.
前記事にて,「モデルを用いたデータベース(DB)のデータ削除方法」を記した.前記事での設定をそのまま引き継いだ上で,本記事では,「モデルを用いたテーブル間の紐づけにおけるon_delete optionの使い方」を記す.
データベース操作においてテーブル間の紐づけは重要であり,同時に,紐づけのために参照するデータが削除された場合,どのようなことが起こるかどうかの知識も非常に重要である.
紐づけた元のデータが削除される場合,"on_delete option"に基づき,振る舞いが決められる.主な振る舞いの5種類を以下にて説明をする.参照は,最下部のURLを確認すること.
- “on_delete = models.CASCADE"の利用
参照するオブジェクトが削除されると,紐づけられたオブジェクトも削除される. - “on_delete = models.PROTECT"の利用
ProtedtedErrorによって,参照するオブジェクトは削除されない. - “on_delete = models.SET_NULL, null = True"の利用
参照するオブジェクトが削除されると,代わりにNULLが入る. - “on_delete = models.RESTRICT"の利用
RestrictedErrorによって,参照するオブジェクトは削除されない. - “on_delete = models.RESTRICT"+"on_delete = models.CASCADE"の利用
参照を参照するオブジェクトが削除されると,紐づけられたオブジェクトも削除されるが,参照するオブジェクトは,RestrictedErrorによって,削除されない.
◆実施環境
Python 3.8.8
Django 3.2.3
(1) テーブルへclassの追加方法
“model_app/models.py"に新たなclass(“Dorayakis", “Shops", “Cities")を追加する.なお,35行目及び44行目にて"on_delete = models.CASCADE"を利用する."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.CASCADE # CASCADEの利用
)
class Meta:
db_table = 'dorayakis'
class Shops(models.Model):
name = models.CharField(max_length=30)
city = models.ForeignKey(
'Cities', on_delete=models.CASCADE # CASCADEの利用
)
class Meta:
db_table = 'shops'
class Cities(models.Model):
name = models.CharField(max_length=30)
class Meta:
db_table = 'cities'
ターミナルを開き,”conda activate 仮想環境名”を実行し,仮想環境に移行する.”model_project”のディレクトリで”python manage.py makemigrations model_app –name add_dora_shop_city”を実行すると,以下が出力される.
Migrations for 'model_app':
model_app\migrations\0002_add_dora_shop_city.py
- Create model Cities
- Create model Shops
- Create model Dorayakis
また,”model_app/migrations”には以下のように"0002_add_dora_shop_city.py"が作成される.
続けて,”model_project”のディレクトリで”python manage.py migrate model_app”を実行すると,以下が出力される.
Operations to perform:
Apply all migrations: model_app
Running migrations:
Applying model_app.0002_add_dora_shop_city... OK
SQLiteをインストールし(詳細はこちら参照),"SQLITE EXPLORER"を開くと,各class(“dorayakis", “shops", “cities")を以下赤枠にて確認できる.
以下のように,"model_project"に新たに"foreignkey_val.py"を作成する.
(2) データベース(DB)へ値の追加方法
DBに値を追加するため,"model_project/foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
adding_vals()
“foreignkey_val.py"で右クリックをすると,以下コマンドが現れるので,"Run Python File in Terminal"をクリックする.DBに上記値が追加される.
その後,"model_project/foreignkey_val.py"に"def getting_dorayakis()"を追記し,以下のように編集する.なお,値は追加したので,"adding_vals()"は削除した.
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')
from django import setup
setup()
from model_app.models import Dorayakis, Shops, Cities
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis(): # 以下追記箇所
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
getting_dorayakis()
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックする.以下がターミナルに出力される.左から"dorayaki_id", “dorayaki_name", “shop_id", “shop_name", “city_id", “city_name"となっている
1 つぶあんどら焼き 1 うさぎや 1 台東区
2 こしあんどら焼き 1 うさぎや 1 台東区
3 クリームどら焼き 1 うさぎや 1 台東区
4 つぶあんどら焼き 2 亀十 1 台東区
5 こしあんどら焼き 2 亀十 1 台東区
6 クリームどら焼き 2 亀十 1 台東区
7 つぶあんどら焼き 3 草月 1 台東区
8 こしあんどら焼き 3 草月 1 台東区
9 クリームどら焼き 3 草月 1 台東区
10 つぶあんどら焼き 4 うさぎや 2 北区
11 こしあんどら焼き 4 うさぎや 2 北区
12 クリームどら焼き 4 うさぎや 2 北区
13 つぶあんどら焼き 5 亀十 2 北区
14 こしあんどら焼き 5 亀十 2 北区
15 クリームどら焼き 5 亀十 2 北区
16 つぶあんどら焼き 6 草月 2 北区
17 こしあんどら焼き 6 草月 2 北区
18 クリームどら焼き 6 草月 2 北区
(3) 値の一部を削除する方法
(A) Shopsを用いた値の削除
1の(2)のデータ一覧(dorayaki_id: 1~18)で,shop_id=1の条件の値(1 うさぎや)を削除する場合,以下を追記する.
“Shops.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Shops.objects.filter(id=1).delete # 追記箇所
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.
実行後の内容を確認するため,"foreignkey_val.py"に記述されている以下(a)を(b)に変更し,再度,"Run Python File in Terminal"をクリックし,実行する.
(a) Shops.objects.filter(id=1).delete
(b) getting_dorayakis()
実行後の結果は以下になる.shop_id=1の条件の値(1 うさぎや)は3件(dorayaki_id: 1~3)あったが,すべて削除された.
4 つぶあんどら焼き 2 亀十 1 台東区
5 こしあんどら焼き 2 亀十 1 台東区
6 クリームどら焼き 2 亀十 1 台東区
7 つぶあんどら焼き 3 草月 1 台東区
8 こしあんどら焼き 3 草月 1 台東区
9 クリームどら焼き 3 草月 1 台東区
10 つぶあんどら焼き 4 うさぎや 2 北区
11 こしあんどら焼き 4 うさぎや 2 北区
12 クリームどら焼き 4 うさぎや 2 北区
13 つぶあんどら焼き 5 亀十 2 北区
14 こしあんどら焼き 5 亀十 2 北区
15 クリームどら焼き 5 亀十 2 北区
16 つぶあんどら焼き 6 草月 2 北区
17 こしあんどら焼き 6 草月 2 北区
18 クリームどら焼き 6 草月 2 北区
(B) Citiesを用いた値の削除
1の(3)の(A)データ一覧(dorayaki_id: 4~18)で,city_id=1の条件の値(1 台東区)を削除する場合,以下を追記する.
“Cities.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Cities.objects.filter(id=1).delete # 追記箇所
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後の内容を確認するため,"foreignkey_val.py"に記述されている以下(a)を(b)に変更し,再度,"Run Python File in Terminal"をクリックし,実行する.
(a) Cities.objects.filter(id=1).delete
(b) getting_dorayakis()
実行後の結果は以下になる.cities_id=1の条件の値(1 台東区)は6 件(dorayaki_id: 4~9)あったが,すべて削除された.
10 つぶあんどら焼き 4 うさぎや 2 北区
11 こしあんどら焼き 4 うさぎや 2 北区
12 クリームどら焼き 4 うさぎや 2 北区
13 つぶあんどら焼き 5 亀十 2 北区
14 こしあんどら焼き 5 亀十 2 北区
15 クリームどら焼き 5 亀十 2 北区
16 つぶあんどら焼き 6 草月 2 北区
17 こしあんどら焼き 6 草月 2 北区
18 クリームどら焼き 6 草月 2 北区
(4) テーブルの不適用・削除
次の章にて異なるon_deleteオプションを記すため,以下にて,"0002_add_dora_shop_city"の適用を外し,削除を行う.
ターミナルを開き,仮想環境に移行する.”model_project”のディレクトリで”python manage.py showmigrations model_app”を実行すると,以下が出力される.
model_app
[X] 0001_add_cake
[X] 0002_add_dora_shop_city
続けて,"python manage.py migrate model_app 0001_add_cake"を実行すると,ターミナルに以下が出力される."0002_add_dora_shop_city"が不適用になる.
Running migrations:
Rendering model states... DONE
Unapplying model_app.0002_add_dora_shop_city... OK
以下プロジェクトの構成で,"model_app/migrations/0002_add_dora_shop_city"を削除する.
(1) テーブルへclassの追加方法
“model_app/models.py"の"CASCADE"を"PROTECT"に変更する."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.PROTECT # 修正箇所(CASCADE => PROTECT)
)
class Meta:
db_table = 'dorayakis'
class Shops(models.Model):
name = models.CharField(max_length=30)
city = models.ForeignKey(
'Cities', on_delete=models.PROTECT # 修正箇所(CASCADE => PROTECT)
)
class Meta:
db_table = 'shops'
class Cities(models.Model):
name = models.CharField(max_length=30)
class Meta:
db_table = 'cities'
ターミナルを開き,”conda activate 仮想環境名”を実行し,仮想環境に移行する.”model_project”のディレクトリで”python manage.py makemigrations model_app –name add_dora_shop_city”を実行すると,以下が出力される.
Migrations for 'model_app':
model_app\migrations\0002_add_dora_shop_city.py
- Create model Cities
- Create model Shops
- Create model Dorayakis
1と同様に,”model_app/migrations”には以下のように"0002_add_dora_shop_city.py"が作成される.
続けて,”model_project”のディレクトリで”python manage.py migrate model_app”を実行すると,以下が出力される.
Operations to perform:
Apply all migrations: model_app
Running migrations:
Applying model_app.0002_add_dora_shop_city... OK
(2) データベース(DB)へ値の追加方法
DBに値を追加およびターミナルへの値出力も同時に実行するため,"model_project/foreignkey_val.py"を以下のように編集する.どちらも1の(2)で実施済み.
・def adding_vals(): DBへの値追加
・def getting dorayakis(): DBへ追加した値の出力
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')
from django import setup
setup()
from model_app.models import Dorayakis, Shops, Cities
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
adding_vals()
getting_dorayakis()
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行すると以下が出力する.
1 つぶあんどら焼き 1 うさぎや 1 台東区
2 こしあんどら焼き 1 うさぎや 1 台東区
3 クリームどら焼き 1 うさぎや 1 台東区
4 つぶあんどら焼き 2 亀十 1 台東区
5 こしあんどら焼き 2 亀十 1 台東区
6 クリームどら焼き 2 亀十 1 台東区
7 つぶあんどら焼き 3 草月 1 台東区
8 こしあんどら焼き 3 草月 1 台東区
9 クリームどら焼き 3 草月 1 台東区
10 つぶあんどら焼き 4 うさぎや 2 北区
11 こしあんどら焼き 4 うさぎや 2 北区
12 クリームどら焼き 4 うさぎや 2 北区
13 つぶあんどら焼き 5 亀十 2 北区
14 こしあんどら焼き 5 亀十 2 北区
15 クリームどら焼き 5 亀十 2 北区
16 つぶあんどら焼き 6 草月 2 北区
17 こしあんどら焼き 6 草月 2 北区
18 クリームどら焼き 6 草月 2 北区
(3) 値の一部を削除する方法
(A) Shopsを用いた値の削除
2の(2)のデータ一覧(dorayaki_id: 1~18)で,shop_id=1の条件の値(1 うさぎや)を削除する場合,以下を追記する.
“Shops.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Shops.objects.filter(id=1).delete
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後,対象となる値は削除されず,ターミナルには以下エラーが出力される.
raise ProtectedError(
django.db.models.deletion.ProtectedError:
("Cannot delete some instances of model 'Shops' because they are
referenced through protected foreign keys: 'Dorayakis.shop'.",
{<Dorayakis: Dorayakis object (1)>, <Dorayakis: Dorayakis object (2)>,
<Dorayakis: Dorayakis object (3)>})
(B) Citiesを用いた値の削除
2の(2)のデータ一覧(dorayaki_id: 1~18)で,city_id=1の条件の値(1 台東区)を削除する場合,以下を追記する.
“Cities.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Cities.objects.filter(id=1).delete # 追記箇所
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後,ターミナルには以下エラーが出力される.
raise ProtectedError(
django.db.models.deletion.ProtectedError:
("Cannot delete some instances of model 'Cities' because they are
referenced through protected foreign keys: 'Shops.city'.",
{<Shops: Shops object (1)>, <Shops: Shops object (2)>,
<Shops: Shops object (3)>})
(4) テーブルの不適用・削除
次の章にて異なるon_deleteオプションを記すため,1の(4)と同様に,"0002_add_dora_shop_city"の適用を外し,削除を行う.
(1) テーブルへclassの追加方法
“model_app/models.py"の"PROTECT"を"SET_NULL, null = True"に変更する."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.SET_NULL, null=True # 修正箇所(PROTECT => SET_NULL, null=True)
)
class Meta:
db_table = 'dorayakis'
class Shops(models.Model):
name = models.CharField(max_length=30)
city = models.ForeignKey(
'Cities', on_delete=models.SET_NULL, null=True # 修正箇所(PROTECT => SET_NULL, null=True)
)
class Meta:
db_table = 'shops'
class Cities(models.Model):
name = models.CharField(max_length=30)
class Meta:
db_table = 'cities'
ターミナルを開き,”conda activate 仮想環境名”を実行し,仮想環境に移行する.”model_project”のディレクトリで”python manage.py makemigrations model_app –name add_dora_shop_city”を実行すると,以下が出力される.
Migrations for 'model_app':
model_app\migrations\0002_add_dora_shop_city.py
- Create model Cities
- Create model Shops
- Create model Dorayakis
1と同様に,”model_app/migrations”には以下のように"0002_add_dora_shop_city.py"が作成される.
続けて,”model_project”のディレクトリで”python manage.py migrate model_app”を実行すると,以下が出力される.
Operations to perform:
Apply all migrations: model_app
Running migrations:
Applying model_app.0002_add_dora_shop_city... OK
(2) データベース(DB)へ値の追加方法
DBに値を追加およびターミナルへの値出力も同時に実行するため,"model_project/foreignkey_val.py"を以下のように編集する.1の(2)および2の(2)で実施済み.
・def adding_vals(): DBへの値追加
・def getting dorayakis(): DBへ追加した値の出力
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')
from django import setup
setup()
from model_app.models import Dorayakis, Shops, Cities
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
adding_vals()
getting_dorayakis()
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行すると以下が出力する.
1 つぶあんどら焼き 1 うさぎや 1 台東区
2 こしあんどら焼き 1 うさぎや 1 台東区
3 クリームどら焼き 1 うさぎや 1 台東区
4 つぶあんどら焼き 2 亀十 1 台東区
5 こしあんどら焼き 2 亀十 1 台東区
6 クリームどら焼き 2 亀十 1 台東区
7 つぶあんどら焼き 3 草月 1 台東区
8 こしあんどら焼き 3 草月 1 台東区
9 クリームどら焼き 3 草月 1 台東区
10 つぶあんどら焼き 4 うさぎや 2 北区
11 こしあんどら焼き 4 うさぎや 2 北区
12 クリームどら焼き 4 うさぎや 2 北区
13 つぶあんどら焼き 5 亀十 2 北区
14 こしあんどら焼き 5 亀十 2 北区
15 クリームどら焼き 5 亀十 2 北区
16 つぶあんどら焼き 6 草月 2 北区
17 こしあんどら焼き 6 草月 2 北区
18 クリームどら焼き 6 草月 2 北区
(3) 値の一部を削除する方法
(A) Shopsを用いた値の削除
3の(2)のデータ一覧(dorayaki_id: 1~18)で,shop_id=1の条件の値(1 うさぎや)を削除する場合,以下を追記する.
“Shops.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Shops.objects.filter(id=1).delete
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後,"SQLITE EXPLORER"を開き,"dorayakis"と"shops"を右クリックし,"Show Table"をクリックする.
“dorayakis"テーブルでは,以下のように"shop_id=1″が削除され,代わりに"NULL"が入力される.
“shops"テーブルでは,以下のように"shop_id=1″が削除された.
“cities"テーブルでは,以下のように何も変化はなかった.
(B) Citiesを用いた値の削除
3の(2)のデータ一覧(dorayaki_id: 1~18)で,city_id=1の条件の値(1 台東区)を削除する場合,以下を追記する.
“Cities.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Cities.objects.filter(id=1).delete # 追記箇所
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後,"SQLITE EXPLORER"を開き,"dorayakis"と"shops", “cities"を各々右クリックし,"Show Table"をクリックする.
“dorayakis"テーブルでは,3の(A)の結果と変わらず,"shop_id=1″には"NULL"が格納されている.
“shops"テーブルでは,以下のように"city_id=1″が削除され,代わりに"NULL"が入力される.
“cities"テーブルでは,以下のように"city_id=1″が削除された.
(4) テーブルの不適用・削除
次の章にて異なるon_deleteオプションを記すため,2の(4)と同様に,"0002_add_dora_shop_city"の適用を外し,削除を行う.
(1) テーブルへclassの追加方法
“model_app/models.py"の"SET_NULL, null = True"を"RESTRICT"に変更する."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 # 修正箇所(SET_NULL, null=True => RESTRICT)
)
class Meta:
db_table = 'dorayakis'
class Shops(models.Model):
name = models.CharField(max_length=30)
city = models.ForeignKey(
'Cities', on_delete=models.RESTRICT # 修正箇所(SET_NULL, null=True => RESTRICT)
)
class Meta:
db_table = 'shops'
class Cities(models.Model):
name = models.CharField(max_length=30)
class Meta:
db_table = 'cities'
ターミナルを開き,”conda activate 仮想環境名”を実行し,仮想環境に移行する.”model_project”のディレクトリで”python manage.py makemigrations model_app –name add_dora_shop_city”を実行すると,以下が出力される.
Migrations for 'model_app':
model_app\migrations\0002_add_dora_shop_city.py
- Create model Cities
- Create model Shops
- Create model Dorayakis
”model_app/migrations”には以下のように"0002_add_dora_shop_city.py"が作成される.
続けて,”model_project”のディレクトリで”python manage.py migrate model_app”を実行すると,以下が出力される.
Operations to perform:
Apply all migrations: model_app
Running migrations:
Applying model_app.0002_add_dora_shop_city... OK
(2) データベース(DB)へ値の追加方法
DBに値を追加およびターミナルへの値出力も同時に実行するため,"model_project/foreignkey_val.py"を以下のように編集する.1の(2),2の(2)および3の(2)で実施済み.
・def adding_vals(): DBへの値追加
・def getting dorayakis(): DBへ追加した値の出力
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')
from django import setup
setup()
from model_app.models import Dorayakis, Shops, Cities
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
adding_vals()
getting_dorayakis()
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行すると以下が出力する.
1 つぶあんどら焼き 1 うさぎや 1 台東区
2 こしあんどら焼き 1 うさぎや 1 台東区
3 クリームどら焼き 1 うさぎや 1 台東区
4 つぶあんどら焼き 2 亀十 1 台東区
5 こしあんどら焼き 2 亀十 1 台東区
6 クリームどら焼き 2 亀十 1 台東区
7 つぶあんどら焼き 3 草月 1 台東区
8 こしあんどら焼き 3 草月 1 台東区
9 クリームどら焼き 3 草月 1 台東区
10 つぶあんどら焼き 4 うさぎや 2 北区
11 こしあんどら焼き 4 うさぎや 2 北区
12 クリームどら焼き 4 うさぎや 2 北区
13 つぶあんどら焼き 5 亀十 2 北区
14 こしあんどら焼き 5 亀十 2 北区
15 クリームどら焼き 5 亀十 2 北区
16 つぶあんどら焼き 6 草月 2 北区
17 こしあんどら焼き 6 草月 2 北区
18 クリームどら焼き 6 草月 2 北区
(3) 値の一部を削除する方法
(A) Shopsを用いた値の削除
4の(2)のデータ一覧(dorayaki_id: 1~18)で,shop_id=1の条件の値(1 うさぎや)を削除する場合,以下を追記する.
“Shops.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Shops.objects.filter(id=1).delete
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後,対象となる値は削除されず,ターミナルには以下エラーが出力される.
raise RestrictedError(
django.db.models.deletion.RestrictedError:
("Cannot delete some instances of model 'Shops' because they are
referenced through restricted foreign keys: 'Dorayakis.shop'.",
{<Dorayakis: Dorayakis object (1)>, <Dorayakis: Dorayakis object (2)>,
<Dorayakis: Dorayakis object (3)>})
(B) Citiesを用いた値の削除
4の(2)のデータ一覧(dorayaki_id: 1~18)で,city_id=1の条件の値(1 台東区)を削除する場合,以下を追記する.
“Cities.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Cities.objects.filter(id=1).delete # 追記箇所
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後,ターミナルには以下エラーが出力される.
raise RestrictedError(
django.db.models.deletion.RestrictedError:
("Cannot delete some instances of model 'Cities' because they are
referenced through restricted foreign keys: 'Shops.city'.",
{<Shops: Shops object (1)>, <Shops: Shops object (2)>,
<Shops: Shops object (3)>})
(4) テーブルの不適用・削除
次の章にて異なるon_deleteオプションを記すため,3の(4)と同様に,"0002_add_dora_shop_city"の適用を外し,削除を行う.
(1) テーブルへclassの追加方法
“model_app/models.py"の一部を"RESTRICT"と"CASCADE"に変更する."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( # 追加箇所(37~39行目)
'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'
ターミナルを開き,”conda activate 仮想環境名”を実行し,仮想環境に移行する.”model_project”のディレクトリで”python manage.py makemigrations model_app –name add_dora_shop_city”を実行すると,以下が出力される.
Migrations for 'model_app':
model_app\migrations\0002_add_dora_shop_city.py
- Create model Cities
- Create model Shops
- Create model Dorayakis
”model_app/migrations”には以下のように"0002_add_dora_shop_city.py"が作成される.
続けて,”model_project”のディレクトリで”python manage.py migrate model_app”を実行すると,以下が出力される.
Operations to perform:
Apply all migrations: model_app
Running migrations:
Applying model_app.0002_add_dora_shop_city... OK
(2) データベース(DB)へ値の追加方法
DBに値を追加およびターミナルへの値出力も同時に実行するため,"model_project/foreignkey_val.py"を以下のように編集する.前回と違い,"city=city"を追加する.
・def adding_vals(): DBへの値追加
・def getting dorayakis(): DBへ追加した値の出力
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','model_project.settings')
from django import setup
setup()
from model_app.models import Dorayakis, Shops, Cities
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
city=city, # 追記箇所
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
adding_vals()
getting_dorayakis()
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行すると以下が出力する.
1 つぶあんどら焼き 1 うさぎや 1 台東区
2 こしあんどら焼き 1 うさぎや 1 台東区
3 クリームどら焼き 1 うさぎや 1 台東区
4 つぶあんどら焼き 2 亀十 1 台東区
5 こしあんどら焼き 2 亀十 1 台東区
6 クリームどら焼き 2 亀十 1 台東区
7 つぶあんどら焼き 3 草月 1 台東区
8 こしあんどら焼き 3 草月 1 台東区
9 クリームどら焼き 3 草月 1 台東区
10 つぶあんどら焼き 4 うさぎや 2 北区
11 こしあんどら焼き 4 うさぎや 2 北区
12 クリームどら焼き 4 うさぎや 2 北区
13 つぶあんどら焼き 5 亀十 2 北区
14 こしあんどら焼き 5 亀十 2 北区
15 クリームどら焼き 5 亀十 2 北区
16 つぶあんどら焼き 6 草月 2 北区
17 こしあんどら焼き 6 草月 2 北区
18 クリームどら焼き 6 草月 2 北区
“dorayakis"を右クリックをし,"Show Table"を確認すると,5の(2)でcity=cityを追記したので,以下赤枠のように"city_id"が追加された.
(3) 値の一部を削除する方法
(A) Shopsを用いた値の削除
5の(2)のデータ一覧(dorayaki_id: 1~18)で,shop_id=1の条件の値(1 うさぎや)を削除する場合,以下を追記する.
“Shops.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
city=city,
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Shops.objects.filter(id=1).delete
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後,対象となる値は削除されず,ターミナルには以下エラーが出力される.
raise RestrictedError(
django.db.models.deletion.RestrictedError:
("Cannot delete some instances of model 'Shops' because they are
referenced through restricted foreign keys:
'Dorayakis.shop'.", {<Dorayakis: Dorayakis object (1)>,
<Dorayakis: Dorayakis object (2)>, <Dorayakis: Dorayakis object (3)>})
(B) Citiesを用いた値の削除
5の(2)のデータ一覧(dorayaki_id: 1~18)で,city_id=1の条件の値(1 台東区)を削除する場合,以下を追記する.
“Cities.objects.filter(id=1).delete"
“foreignkey_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
cities = ['台東区','北区',]
shops = ['うさぎや','亀十','草月']
dorayakis = ['つぶあんどら焼き','こしあんどら焼き','クリームどら焼き']
def adding_vals():
for city_name in cities:
city = Cities(
name=city_name
)
city.save()
for shop_name in shops:
shop = Shops(
name=shop_name,
city=city
)
shop.save()
for dorayaki_name in dorayakis:
dorayaki = Dorayakis(
name=dorayaki_name,
price=200,
birthday='1913-01-01',
city=city,
shop=shop
)
dorayaki.save()
def getting_dorayakis():
dorayakis = Dorayakis.objects.all()
for dorayaki in dorayakis:
print(dorayaki.id,dorayaki.name,dorayaki.shop.id,dorayaki.shop.name,dorayaki.shop.city.id,dorayaki.shop.city.name)
Cities.objects.filter(id=1).delete # 追記箇所
“foreignkey_val.py"で右クリックをし,"Run Python File in Terminal"をクリックし,実行する.実行後,"SQLITE EXPLORER"を開き,"dorayakis"と"shops", “cities"を各々右クリックし,"Show Table"をクリックする.
“dorayakis"テーブルでは,以下のように"city_id=1″の値が削除された.
“shops"テーブルでは,以下のように"city_id=1″が削除された.
“cities"テーブルでは,以下のように"city_id=1″が削除された.
(4) テーブルの不適用・削除
次の章にて異なるon_deleteオプションを記すため,4の(4)と同様に,"0002_add_dora_shop_city"の適用を外し,削除を行う.
■参照
https://docs.djangoproject.com/ja/3.1/ref/models/fields/#module-django.db.models.fields.related
以上