LoginSignup
2
3

More than 3 years have passed since last update.

Django Serializerを使って参照モデルを取得する

Last updated at Posted at 2020-10-21

Serializerを簡単にいうと!

モデルオブジェクトをJSONに変換してくれる!

それでは
今回はBookオブジェクトを取得する際に、
ForeignKeyで参照しているAuthorをオブジェクトも含めて取得します!!!!!!!!!!!!

modelを定義する

サンプルのモデルです!
BookモデルはAuthorモデルを参照しています!

models.py
class AbstractModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    is_deleted = models.CharField(max_length=1, default='0')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class Author(AbstractModel):
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)

class Book(AbstractModel):
    title = models.CharField(max_length=128)]
    sub_title = models.CharField(max_length=128)]
    price = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    author = models.ForeignKey(Author, on_delete=models.PROTECT, blank=True, null=True)

参照元のモデルも一緒に取得する

Viewを定義する

genericsのListAPIViewを使って取得APIを作成します!
authorモデルも取得するのでquerysetには
select_relatedでauthorを指定しておきます。
all()なのでも取得することは可能ですが、select_related.('author')
事前に指定しておくことで、発行するSQLを削減できます!!

views.py
from django_filters import rest_framework as filters
from rest_framework import generics

from book.models import Book, Author
from book.serializers import BookSerializer

class ListBook(generics.ListAPIView):
    """Bookを一覧取得するAPI"""
    queryset = Book.objects.select_related('author')
    serializer_class = BookSerializer
    filter_backends = [filters.DjangoFilterBackend]
    filterset_fields = '__all__'

Serializerに参照元Serializerを定義する

BookSerializerのフィールドに関連先Serializerを定義することができます!
これで関連先のモデルも取得することができます!!!

ただここで一つ注意なのは参照元のserializerを
定義する時にフィールド名がlookupに関係しているので間違えないようにしてください!!

serializer.py
class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = '__all__'


class BookSerializer(serializers.ModelSerializer):
    author = AuthorSerializer()
    class Meta:
        model = Book
        fields = '__all__'

結果がこちらです!!!!

出力結果にはサンプルモデルでは省いたデータも出力されちゃってます!!
飛ばしてください!!

スクリーンショット 2020-10-22 3.59.33.png

参照先のモデルを取得する

先ほどは、Bookモデルと参照元のAuthorモデルも取得しましたが、
逆に、AuthorからBookを取得したいと思います!!。
方法は簡単です!

Viewを定義する

ListAPIViewを使って取得していきたいと思います。
今回は、select_relatedなどせずにそのままall()で問題ありません。

views.py
class ListAuthor(generics.ListAPIView):
    """Authorを取得する"""
    queryset = Author.objects.all()
    serializer_class = AuthorBookSerializer
    filter_backends = [filters.DjangoFilterBackend]
    filterset_fields = '__all__'

Serializerの定義

参照先のモデルを取得するため、book_setとなっています!
これでAPIをリクエストするとAuthorとBookが取得することができます。
この時に、BookSerializerauthor = AuthorSerializer()を残しておくと
book取得した時にさらにauthorを再び取得してしまうので注意。

serializers.py
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'


class AuthorBookSerializer(serializers.ModelSerializer):
    book_set = BookSerializer(many=True)
    class Meta:
        model = Author
        fields = '__all__'

結果がこちらです!!!!

スクリーンショット 2020-10-22 3.51.45.png

以上になります!

2
3
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
2
3