DRF で association を持ったデータを serialize する

thumbnail

Django REST framework の serializer で関連情報を扱う。

今日は簡略化したモデルで考える。Author has many books という著者が複数の本を書いている状態を考える。なお共著は存在せず、一冊の本は一人の著者に紐づくという前提に立つ。

model を考える

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return str(self.id)

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author)

    def __str__(self):
        return str(self.id)

とする。

これは migration すると book table に author_id という author に対する外部キーが生成される。

著者に本一覧を含めて返す serializer

ではまず、一人の著者のデータを返す時に、本のデータも返すようにしよう。

class AuthorSerializer(serializers.ModelSerializer):
    books = BookSerializer(read_only=True, many=True)
    class Meta:
        model = Battle
        fields = ('id', 'name', 'books')

親は子の serializer を呼び出せるので、BookSerializer を使えば良い。

本に著者情報を含めて返す serializer

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'title', 'author']
        depth = 1

子は親の serializer を呼び出せないので(親が子を読んでいる場合、モジュールの循環参照になるため)、depth を使う。

もし depth がなければ author は外部キーの数字が帰る。Book モデルは author = models.ForeignKey(Author) というフィールドを持つので仕方ない。 ただそこで depth を持ってさえいればそのオブジェクトのまま渡すことができる。

The default ModelSerializer uses primary keys for relationships, but you can also easily generate nested representations using the depth option:

FYI: https://www.django-rest-framework.org/api-guide/serializers/#specifying-nested-serialization