django が便利な理由の一つとして、多対多のモデルのテーブルを ManyToManyField で簡単に作れるというものがあります。厳密にいうと中間テーブルを自動で生成してくれます。今回はこの ManyToManyField を使った場合、登録フォームはどのように実装すればいいかを備忘録として残します。
ManyToManyField を使ったモデル
Django 公式のドキュメントを引用する(一部変更)。Publication (出版物)と Article (記事)が多対多の関係になっている。
この時、 ManyToManyField はどちらか片方にだけ設定されている。
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")
class Meta:
ordering = ['headline']
def __str__(self):
return self.headline
さらに加えて注目したいのが、 ManyToManyField に related_name を与えていることである。ここが引用元の公式ドキュメントには無かった部分。
これは「もう一方のモデルから見たとき、このモデルを何と呼べばいいか」を設定するものであり、後に使えるので分かりやすい名前を付けておく。
Article 登録時に Publication を付与
ManyToManyField を持つ方のモデルのレコードを新たに登録する時に、もう一方のモデルのオブジェクトを付与するときはビューファイルのフォーム処理をしているクラスの、 save() の直後に以下のように書く。
(省略)
article_obj.save()
# ここから
publication_obj = Publication(id=2) # 付与したいオブジェクトを取得
article_obj.publications.add(publication_obj)
(省略)
Publication 登録時に Article を付与
(省略)
publication_obj.save()
# ここから
article_obj =Article(id=1) # 付与したいオブジェクトを取得
publication_obj.articles.add(article_obj)
(省略)
基本的にはさっきと同じだが、ここで先ほどモデルで設定した related_name が役に立つ。 publication から見た article は「 articles 」という名前で呼べることになっているのでそれをそのまま使う。