Djangoで出てくるthroughとは

📕 新コースを公開しました。→クーポン掲載ページ

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で使用していますが、どこでも使えます。気になった方は中間テーブルの中身を確認してみるのもいいかもしれませんね。

🎓✍️コース一覧

プログラミング関係のビデオコースを提供しています。クーポンも発行していますので、ぜひ一度チェックしてみてください。

Twitter @takumafujimoto

記事を読んでいただきありがとうございます。ツイッターではプログラミング以外についてや、たまにクーポン情報もツイートしたり。。。ツイッターでもお待ちしてます。