Python・Djangoのリレーションシップを簡単解説

プログラミング
Masa
Masa

こんにちは!Masaです。

今回はDjangoのリレーションについて解説していきます。

こんな方におすすめ!
  • Django初心者で勉強をしている人
  • Djangoのリレーションシップを詳しく知りたい人
  • Djangoに限らず、リレーションシップの考え方を知りたい人

リレーションシップとは

まずリレーションシップとは何かについて解説します。

リレーションシップとは、各データベースの関連性(連携)のことを指します。

SNSの投稿で例えてみましょう。

SNSは各ユーザが自分で写真やテキスト等を投稿できます。
各ユーザのユーザ情報と投稿はデータベースとして別々に管理されているため、ユーザと投稿の連携が必要となります。

この場合、ユーザ情報と投稿を連携することをリレーションシップといいます。

Djangoにおけるリレーションシップの種類と具体例

Djangoにおいて、リレーションシップは3種類あります。(考え方によっては4種類)

リレーションシップの種類
  • 1対1( OneToOneField)
  • 1 対 多( ForeignKey)
  • 多 対 1( ForeignKey)
  • 多 対 多( ManyToManyField)

1対多と多対1は考え方が同じで、主と従を逆にするだけです。
今回の解説では同じものとして扱います。

各リレーションシップの具体例を先ほどのSNSで見ていきましょう。

1対1( OneToOneField)

まずは1対1の関係についてです。

SNSで例えるとSNSで使用するユーザプロフィール(SNSで表示されるもの)本人情報(現実の個人情報)で考えましょう。

本人情報とプロフィールはお互いに1つしかないので1対1の関係となります。
実際は別けなくても成り立たせることはできますが、アクセス権の問題や利便性を考えてこのようにすることがあります。

実際にDjangoでモデルを作成するとこのようになります。

from django.db import models

class User(models.Model):
    GENDER_CHOICES = (
        ('1', '女性'),
        ('2', '男性'),
        ('3', 'その他'),
    )

    name = models.CharField(max_length=40)
    number = models.IntegerField()
    mail = models.EmailField(max_length=200)
    password = models.CharField(max_length=40)

    def __str__(self):
        return self.name

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    display_name = models.CharField(max_length=40)
    introductory_essay = models.TextFiedl(max_length=300)
    gender = models.CharField('性別', choices=GENDER_CHOICES)

    def __str__(self):
        return self.display_name

本人情報(User)が主、プロフィールが従とします。

主のユーザに関しては通常のモデルと同じように作成すれば問題ありません。

従の方でuser項目を作成しリレーションシップを構築しています。

従側の項目では以下のように1対多のリレーションシップを構築します。

項目 = models.OneToOneField(主のモデル名, on_delete=models.CASCADE)

“on_delete=”は主であるユーザのデータが削除された時の処理を記述しています。
一覧は以下の通りです。

記述内容処理内容
models.CASCADE全て削除します
models.PROTECT関連付けられているオブジェクトがあると削除できない
models.SET_NULLNULLがセットされる
models.SET_DEFAULT削除されたオブジェクトに変わり、デフォルト値が入る
models.SET()処理を自由に設定できる

今回はmodels.CASCADEなので、本人情報を削除するとリレーションシップを構成しているプロフィールも削除されます。

1 対 多( ForeignKey)

次に1対多の関係です。

これはユーザ投稿の関係が当てはまります。

各ユーザがそれぞれ投稿したと仮定します。
ユーザAの投稿は投稿1,投稿2、投稿3、ユーザBの投稿は投稿4、投稿5といったイメージです。

ユーザが1対多の1の側に、投稿が多の側になり、それぞれリレーションシップが成り立っています。

これをDjangoでモデル例を作成すると以下のようになります。

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    mail = models.EmailField(max_length=200)
    age = models.IntegerField()
    birthday = models.DateField()

    def __str__(self):
        return self.name

class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateTimeField()
    content = models.TextFiedl(max_length=300)

  def __str__(self):
        return self.content

ユーザが主、投稿を従とします。

1対多も同様に、主のユーザに関しては通常のモデルと同じように作成すれば問題ありません。
従の投稿では、項目をユーザ、投稿日時、テキスト内容の3つとしました。
この時のユーザ項目でForeignKeyを使用してリレーションシップを追加します。

従側の項目では以下のように1対多のリレーションシップを構築します。

項目 = models.ForeignKey(主のモデル名, on_delete=models.CASCADE)

多 対 多( ManyToManyField)

最後に多対多の関係です。

これは投稿タグ(ハッシュタグ)の関係が当てはまります。

投稿1ではブログプログラミングがタグされていますが、ブログは投稿3で、プログラミングは投稿2でも使用されています。
これが多対多のリレーションシップの関係のイメージとなります。

これをDjangoのモデルで作成すると以下のようになります。

from django.db import models

class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateTimeField()
    content = models.TextFiedl(max_length=300)

class Tag(models.Model):
    post = models.ManyToManyField(Post)
    tag_name = models.CharField(max_length=50)

    def __str__(self):
        return self.tag_name

Postは1対多のPostをそのまま使用しています。

Postを主、タグを従とします
多対多でも主側のPostは通常通りモデルを作成すれば問題ありません。

従側の項目では以下のようにして多対多のリレーションシップを構築します。

項目 = models.ManyToManyField(主のモデル名)

まとめ

今回はDjangoにおけるリレーションシップについてでした。

1対1、1対多(多対1)、多対多の3種類があり、用途に応じて使い分けます。

リレーションシップはデータベースを構築する際に重要になってきます。
個人レベルでWebアプリを作成する際にも使用するので、マストな技術だと思います。

ぜひ頑張ってマスターしましょう💪

最後まで読んでいただきありがとうございます。
自己学習に役立てていただけたら嬉しく思います
またSNSやブログでシェアしていただくことや、誤植などをコメントで指摘いただけたら幸いです。

コメント

タイトルとURLをコピーしました