■この記事を読むとわかること
- Djangoでmysqlの簡単なjoinの方法が分かる
- joinされた側のデータがどこにあるのか分かる
データの準備
説明の前に、どのようなデータを扱うのか解説します。
今回は、本と(本の)ジャンルの管理の例で解説します。
ジャンルマスターがあり、本には必ずジャンルマスターのIDを持っている状態になります。
■ジャンルマスター
m_genre
■本マスター
m_books
データ構成は以下の通り。
m_genreテーブル
m_booksテーブル
DB(データベース)にデータを流し込むためsqlを用意します。
今回は、すぐに試せるようにcreate文、insert文を用意しました。
CREATE TABLE `m_genre` (
`id` int(11) NOT NULL,
`name` varchar(45) DEFAULT NULL COMMENT 'ジャンル名',
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
`del` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `` (`id`,`name`,`created`,`modified`,`del`) VALUES (1,'プログラミング','0000-00-00 00:00:00',NULL,0);
INSERT INTO `` (`id`,`name`,`created`,`modified`,`del`) VALUES (2,'家事代行',NULL,NULL,0);
INSERT INTO `` (`id`,`name`,`created`,`modified`,`del`) VALUES (3,'動物図鑑',NULL,NULL,0);
CREATE TABLE `m_books` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`genre_id` int(11) DEFAULT NULL COMMENT 'ジャンルID m_genre.idの外部参照',
`name` varchar(45) DEFAULT NULL COMMENT '名前',
`count` int(10) DEFAULT '0' COMMENT '在庫',
`created` datetime NOT NULL,
`modified` datetime DEFAULT NULL,
`del` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`,`created`),
UNIQUE KEY `uniqe` (`id`,`created`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT INTO `` (`id`,`genre_id`,`name`,`count`,`created`,`modified`,`del`) VALUES (1,1,'プログラミング1',2,'0000-00-00 00:00:00',NULL,0);
INSERT INTO `` (`id`,`genre_id`,`name`,`count`,`created`,`modified`,`del`) VALUES (2,1,'プログラミング2',10,'0000-00-00 00:00:00',NULL,0);
INSERT INTO `` (`id`,`genre_id`,`name`,`count`,`created`,`modified`,`del`) VALUES (3,2,'家事代行1',2,'0000-00-00 00:00:00',NULL,0);
INSERT INTO `` (`id`,`genre_id`,`name`,`count`,`created`,`modified`,`del`) VALUES (4,2,'家事代行2',2,'0000-00-00 00:00:00',NULL,0);
INSERT INTO `` (`id`,`genre_id`,`name`,`count`,`created`,`modified`,`del`) VALUES (5,2,'家事代行3',2,'0000-00-00 00:00:00',NULL,0);
実際にjoinするコードを書いてみる
データが準備できたら以下のようにコードを書きます。
models.py
from django.db import models
class MGenre(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=45, blank=True, null=True)
created = models.DateTimeField(blank=True, null=True)
modified = models.DateTimeField(blank=True, null=True)
del_field = models.IntegerField(db_column='del') # Field renamed because it was a Python reserved word.
class Meta:
managed = False
db_table = 'm_genre'
class MBooks(models.Model):
#DBのカラム名は「genre_id」だが、idの部分は削除すること
#ForeignKeyを使って、MGenre側(MGenre.id)を参照する
genre = models.ForeignKey(MGenre, on_delete=models.CASCADE)
name = models.CharField(max_length=45, blank=True, null=True)
count = models.IntegerField(blank=True, null=True)
created = models.DateTimeField()
modified = models.DateTimeField(blank=True, null=True)
del_field = models.IntegerField(db_column='del') # Field renamed because it was a Python reserved word.
class Meta:
managed = False
db_table = 'm_books'
unique_together = (('id', 'created'), ('id', 'created'),)
上記のように
bookにgenreIDに対して外部キーの設定をする。
ForeignKey」を指定することにより、genru側のデータを取れるようになります。
view側の実際のコードは以下の通り。
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import MBooks, MGenre
def index(request):
#通常のクエリ
book_list = MBooks.objects.filter(genre_id=1).values()
print(book_list)
#https://docs.djangoproject.com/en/3.0/topics/db/queries/#one-to-many-relationships
#本(MBooks)とジャンル(MGenre)のリレーション
#モデル側の設定はgenre = models.ForeignKey(MGenre, on_delete=models.CASCADE)
#この方法でMGenre側のデータを取ることができる。
e = MBooks.objects.get(id=2)
#e.genreと指定することでMGenre側のデータを取得できる
print(e.genre.name)
#1ジャンルで複数の本があるケースでデータ取得
e = MBooks.objects.filter(genre_id=1)
print(e[0].genre.name) #配列1番めのジャンル側のデータ取得してみる
return HttpResponse("Hello, world. You're at the polls index.")
これでjoin側のデータを取ることができました(詳しくはコード内のコメントを参照してください)。
上記の方法は、実装が簡単なのですぐに反映ができる。
データが比較的少ないとき、実装速度を優先させるときに良いと思う。
しかし、sqlの最適化を考える場合は、prefetch_relatedやselect_relatedを使ったほうがよいです。
prefetch_relatedやselect_relatedについては、別の機会に紹介したいと思います!
最後に
最後に、ソースコードの全体が分かるように、GitHubにもコードを上げさせて頂きました。
https://github.com/jshirius/django_book_project
もし必要ならば参考にしてみてください!
\IT未経験者からのサポートあり!転職サービス3選!!/
サービス名 | |||
---|---|---|---|
未経験 | 未経験OK | 未経験の転職専用 | 経験者向け |
公開の求人数 | ITエンジニア全体で1万件以上 ITエンジニア未経験で600件以上 |
未公開 | 5,000件以上 |
利用対象 | 全職種 | IT特化 | IT特化 |
特徴 | ✓誰もが知る転職サービス ✓経歴を登録しておくとオファーが来る |
✓企業担当者と条件交渉 ✓スキルの身につく企業を紹介 |
✓IT専門のエージェントが対応 ✓転職成功すると年収200万円以上の大幅アップがある |
転職サポート内容 |
|
|
|
公式サイト | リクナビネクスト | テックゲート | レバテックキャリア |