LoginSignup
1
0

More than 1 year has passed since last update.

【 Django 】 ManyToMany の中間テーブルを手動で定義して実際に動かすまで

Posted at

ManyToMany Field を使ったモデル

多対多(n対n)で紐づくモデルの設計方法は以前の投稿で書きました。

今回は、ManyToManyField で自動生成される中間テーブルをあえて自分で作成して、独自の中間フィールドを追加して動かすまでを備忘録として残します。

中間テーブルの手動生成

以前のモデルを利用します。

本来は ManyToMany を設定しただけで中間テーブルが自動で生成されるのですが、それだと独自に中間フィールドを設けられないので、手動で中間テーブルを作成します。

以下のようにコードを追加します。

model.py
from django.db import models

class Publication(models.Model):
    """
    出版物モデル
    """

    title = models.CharField(max_length=30)

    class Meta:
        ordering = ['title']

    def __str__(self):
        return self.title

class Article(models.Model):
    """
    記事モデル
    """

    headline = models.CharField(max_length=100)
                   # ↓ここで多対多の設定
    publications = models.ManyToManyField(
        Publication,
        related_name="articles",
        through="PublicationArticleRelation", # ←中間テーブル名の指定を追加
    )

    class Meta:
        ordering = ['headline']

    def __str__(self):
        return self.headline

# ここから中間テーブルの定義(追加)

class PublicationArticleRelation(models.Model):
    """
    出版物と記事の中間モデル
    """

    publication = models.ForeignKey(
        Publication,
        related_name="publication_relation",
        verbose_name="出版物",
        on_delete=models.CASCADE,
    )
    article = models.ForeignKey(
        Article,
        related_name="article_relation",
        verbose_name="記事",
        on_delete=models.CASCADE,
    )
    
    # 独自の中間フィールド
    thema = models.CharField(
        "テーマ", max_length=16,
    )

articleモデルの ManyToManyField のthrough引数と、ソース後半の中間テーブル定義の部分を追加しています。

操作してみる

リレーションの作成例

p1 = Publication.objects.get(id = 1)
a1 = article.objects.get(id = 1)

PublicationArticleRelation.objects.create(
    publication = p1,
    articke = a1,
    thema = "音楽"
)

このように、基本的には普通のモデルと同じように扱うことができる。

上記で作成したリレーションを呼び出すときは以下のようにすれば良い。

# 出版物がp1のリレーション
PublicationArticleRelation.objects.get(publication = p1)

# 記事がa1のリレーション
PublicationArticleRelation.objects.get(article = a1)

# テーマが音楽のリレーション
PublicationArticleRelation.objects.get(thema = "音楽")

# 出版物がp1かつ記事がa1かつテーマが音楽のリレーション
PublicationArticleRelation.objects.get(publication = p1, article = a1, thema = "音楽")
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0