djangoのForeignKeyとは

2022年5月3日

djangoのForeignKeyとは

データにて「1対多」の関係を作るときにmodels.pyに定義します。
例えばある「ユーザー」が「掲示板」に複数回書き込みをしたとします。
すると「ユーザー1人」に対して「複数の書き込みがある」と言う関係は「1対多」ですね。
イメージは下の通りです。

掲示板の例でいうと構造的に「掲示板」のテーブルに、ユーザーのプライマリキーである「ユーザーID」を持たせることでデータの紐づき実現できます。

掲示板情報を元にユーザー情報を取得する事を「参照」と言います。
ユーザー情報を元に掲示板情報を取得する事を「逆参照」と言います。

元となる情報 取得される情報 取得できる情報の数 呼称
掲示板 ユーザー 1個(人) 参照
ユーザー 掲示板 複数個 逆参照

 
実際に特定のユーザーから掲示板テーブルに書き込みをしてForeignKeyの動きを見てみましょう。

models.py

掲示板となるモデルは下のように作成してみました。
下のように設定することで「Thread」テーブルの「user」フィールドに「user_id」が入るようになります。


#--ユーザーモデル--------------------------------------
from django.contrib.auth.models import User
.
.
.
#--掲示板----------------------------------------------
class Thread(models.Model):
    title    = models.CharField(blank=False, null=False, max_length=150)
    subtitle = models.TextField(blank=False, null=False)
    user     = models.ForeignKey(User, on_delete=models.CASCADE)
    created_datetime = models.DateTimeField(auto_now_add=True)
    updated_datetime = models.DateTimeField(auto_now=True)
    def __str__(self):
        return self.title
# [models.ForeignKey] - 紐づけるテーブル(モデル)のプライマリーキーが入る
# [フィールド名]  = models.ForeignKey([モデル名], ...)
# on_delete=models.CASCADE - 紐づくデータが削除されたら自身のレコードを削除する
# on_delete=models.PROTECT - 紐づくデータが削除されても自身のレコードを削除しない
# ※上記の場合Userが削除されたときにThreadのレコードを削除するか否か

admin.py

管理者画面に反映させるために下の通り記述をしてあげましょう。
これで管理者画面からThreadに入力が出来るようになります。


from django.contrib import admin
from .models import Thread
#--掲示板----------------------------------------------
admin.site.register(Thread)

migrate

「migarate」を実行してテーブルを作成してあげましょう。


python3.6 manage.py makemigrations
python3.6 manage.py migrate

管理画面から登録

下の通りユーザーを作成してみました。

管理画面から作成したユーザーで「Thread」に書き込みをしてみます。

結果

下の通り「auth_user」テーブルに「id=2」の「test_user」が作成されているのが確認できます。


MariaDB [app]> select id,username from auth_user;
+----+----------------+
| id | username       |
+----+----------------+
|  1 | houdoukyokucho |
|  2 | test_user      |
+----+----------------+

今度は「app_thread」テーブルを確認してみます。
下の通り「ForeignKey」で作成したフィールド「user_id」にtest_userのid「2」がINSERTされているのが確認できました。


MariaDB [app]> select id, title, user_id from app_thread;
+----+--------------------------+---------+
| id | title                    | user_id |
+----+--------------------------+---------+
|  1 | test                     |       1 |
|  2 | test_userの自己紹介       |       2 |
+----+--------------------------+---------+

2022年5月3日