Udemy講師をしている藤本です。
Djangoコースの中で何気なく使っていた through
について、質問をいただいたので、解説を書き残しておきます。
質問内容
Item.tags.throughはどういう意味があるのでしょうか。
上記の質問の through はコース内では admin.py で使用しました。
...
class TagInline(admin.TabularInline):
model = Item.tags.through
class ItemAdmin(admin.ModelAdmin):
inlines = [TagInline]
exclude = ['tags']
...
サンプルのモデル解説
コースではItemモデルとTagモデルがあって、それらをManyToManyFieldで繋げています。
Itemモデルはアイテム(商品)だと思っていただき、Tagモデルは各アイテムに設定するタグです。
カテゴリーの場合はForeignKeyでいいのですが、タグの場合は少し用途が異なります。
- あるアイテムは複数のタグを持つことが可能です。
- あるタグは複数のアイテムから参照されてOKです。
図にすると下記のような感じです。
例えばItem1はTag1とTag2を持っています。
Tag1を見ると、Tag1はItem1だけでなく、Item2とも繋がっています。
このようなケースでは一対多のForeignKeyでは表現できないのでManyToManyFieldを使っています。
ManyToManyFieldが行なっていること
ManyToManyFieldを使えば多対多を表現できますが、どのようにそれを実現しているかというと、
モデル間(テーブル間)に中間テーブルを作成して実現しています。
つまり今回の例ではItemモデルとTagモデルを直接結びつけるのではなく、中間テーブルを介して間接的に繋げているということです。
図にすると次のようなイメージです。
中間テーブルを介することで、Itemテーブルと中間テーブルはForeignKeyをはることができ、Tagテーブルと中間テーブルに関しても同様です。
中間テーブル自体は参照元IDと参照先IDをレコードとして保持します。
throughは中間テーブルを指す
ManyToManyFieldを使えば中間テーブルが自動的に作成されます。その中間テーブルを呼び出すにはどうすればいいかというと、この時に through
を使います。
今回は through
をadmin.pyの中で設定しています。
この目的を解説しておくと、
まずDjangoはデフォルトで管理画面があります。
(簡単な設定さえすれば)管理画面では各テーブルのレコードを見ることができます。
例えば各アイテムなどです。あるアイテムページを開くと、そのアイテムが持っているフィールドの値を確認することができます。
今回の例ではアイテムはタグを持っているので、タグも表示させたいです。
ただし、タグとは多対多なのでデフォルトでは見栄えがあまり良くないです。なので、見やすくするために TabulerInline
をadmin.pyで設定しています。
TabulerInline
を使うには、どのモデルかを渡さなければいけません。この場合は両方のモデルを参照している中間テーブルを指定してあげます。
そのために through
を使っています。
model = Item.tags.through # この行
そうすることで、あと少しの設定などをすればアイテムページでタグを見やすく表示できます。
以上です。
今回の例ではadmin.pyで使用していますが、どこでも使えます。気になった方は中間テーブルの中身を確認してみるのもいいかもしれませんね。