Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

djangoアプリのリレーション〜1対多編

Posted at

今回のお題

今回のお題はdjangoアプリにおけるリレーションの実装です。

リレーションと一口にいってもいくつかのバリエーションがありますが、今回はその中でも1対多のリレーションについてまとめます。

目次

  • models.py
  • テンプレート
  • おまけ〜select_related
  • 終わりに

models.py

まずはモデルを用意して、その中に両者の関係性を記述します。

今回は例として書籍のレビューサイトを想定します。

一つの書籍に対して複数のレビューが紐づく可能性があります。

models.py
class Book(models.Model):
  title = models.CharField(maxlangth=30)

class Review(models.Model):
  book = models.ForeignKey(Book, on_delete=models.CASCADE)
  text = models.TextField(max_length=200)

注目すべきは、Reviewモデルの以下の部分ですね。

book = models.ForeignKey(Book, on_delete=CASCADE)

関連するbookインスタンスの情報を保存するためにbookというフィールドを定義しています。

フィールドの型はForeignKeyで、第一引数は対象となるモデル、on_deleteオプションはbookインスタンス削除時の挙動です。

今回はon_delete=CASCADEとしているので、あるBookインスタンスが削除されるとそこに紐づくReviewインスタンスも全て削除されます。

以下、その他のon_deleteオプションについて載せておきます。

【PROTECT】
関連するレコードが存在する間は削除ができなくなります。

book = models.ForeignKey(Book, on_delete=models.PROTECT)
# レビューが一つでもある書籍は、先にレビューをレビューを消してからでないと削除できない

【SET_NULL】
関連するレコードが削除されるとNULLが削除される。

null=Trueを設定しておく必要がある。

book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True)
# 関連先の書籍が削除されるとreview.book = nullが自動的に設定される。

【SET_DEFAULT】
関連先のレコード削除時に、あらかじめ決められたデフォルト値を設定する。

defaultオプションの設定が必須。

book = models.ForeignKey(Book, on_delete=models.SET_DEFAULT, default=xxx)

【SET()】
関連先削除時には、引数として与えた値をセットする。

book = models.ForeignKey(Book, on_delete=models.SET(xxx))

テンプレート

関連先のレコードを取得する際には以下のように記述します。

{# 親モデルから子モデルを取得 #}
{{ book.review_set.all }}

{# 子モデルから親モデルを取得 #}
{{ rev.book }}

親から子を取得する際にはxxx_set.allとする必要があります。

また、上記のコードはveiwsで用いることも可能です。

おまけ〜select_related

いわゆるN+1問題を解決するためには、select_relatedメソッドを用いるのが便利です。

以下のようにレコード取得の途中でselect_relatedメソッドを挟むことで、引数として与えた外部キーの情報を同時に取得することができます。

rev = Review.objects.select_related("book").get(id=pk)
book = rev.book

終わりに

以上が1対多のリレーションの基本になります。

気が向けば多数対多数についてもまとめます。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?