3
3

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 5 years have passed since last update.

drf-yasgでForeignKeyのフィールドのパラメータにSerializerを反映させる

Posted at

課題

  • django-rest-framework を使ったWeb APIのドキュメントを、drf-yasgで生成しようとしたところ、modelでForeignKeyとして定義していたパラメータの情報が正しく表示されなかった

環境

  • python3.6.5
  • djangorestframework==3.9.1
  • drf-yasg==1.13.0

サンプルコード

from django.db import models

# Create your models here.


class Article(models.Model):
    title = models.CharField(max_length=100, blank=True, null=True)
    contents_text = models.TextField(blank=True, null=True)
    pubdate = models.DateTimeField(auto_now_add=True)


class User(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)


class Comment(models.Model):
    target_article = models.ForeignKey(Article, on_delete=models.SET_NULL, null=True, related_name='comments')
    comment = models.TextField(blank=True, null=True)
    pubdate = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
from rest_framework.serializers import ModelSerializer
from .models import Article, Comment, User


class UserSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'


class CommentSerializer(ModelSerializer):
    class Meta:
        model = Comment
        fields = [
            'id',
            'target_article',
            'comment',
            'pubdate',
            'user',
        ]


class ArticleSerializer(ModelSerializer):
    class Meta:
        model = Article
        fields = [
            'id',
            'title',
            'contents_text',
            'pubdate',
            'comments',
        ]

  • redocの出力
スクリーンショット 2019-03-03 3.53.13.png

解決方法

  • ArticleSerializercommentsフィールドをSerializerMethodFieldとして定義し、get_commentsArticleに紐づくCommentを取得する
  • CommentSerializeruserフィールドをSerializerMethodFieldとして定義し、get_userメソッドでCommentに紐づくUserを取得する
  • get_commentsメソッドとget_userメソッドに@swagger_serializer_methodデコレータを付加し、それぞれのメソッド内で使うSerializerを指定する
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from .models import Article, Comment, User

from drf_yasg.utils import swagger_serializer_method


class UserSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'


class CommentSerializer(ModelSerializer):
    user = SerializerMethodField()

    class Meta:
        model = Comment
        fields = [
            'id',
            'target_article',
            'comment',
            'pubdate',
            'user',
        ]

    @swagger_serializer_method(serializer_or_field=UserSerializer)
    def get_user(self, instance):
        return UserSerializer(instance.user).data


class ArticleSerializer(ModelSerializer):
    comments = SerializerMethodField()

    class Meta:
        model = Article
        fields = [
            'id',
            'title',
            'contents_text',
            'pubdate',
            'comments',
        ]

    @swagger_serializer_method(serializer_or_field=CommentSerializer)
    def get_comments(self, instance):
        try:
            return CommentSerializer(instance.comments.get(target_article=instance)).data
        except Exception as e:
            print(e)
            return None
  • redocの出力
スクリーンショット 2019-03-03 4.02.39.png

補足

swagger_serializer_methodデコレータをつけないとForeignKeyで取得しようとしているフィールドはstring型として認識される
スクリーンショット 2019-03-03 4.05.18.png

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?