57
50

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.

Django REST Framework メモ ::ForeignKeyでつながっている別モデルをくっつけてひとつのJSONとしてWebAPI出力する

Last updated at Posted at 2018-02-07

###はじめに
Django REST Framework でForeignKeyでつながっている別モデルをくっつけてひとつのJSONとしてWebAPI出力する実装方法です。

転載元ブログ情報

この記事は自分のブログの転載です。
http://k-mawa.hateblo.jp/entry/2018/02/08/000011

###検証した環境

  • Django2
  • Python3.5.2

###モデルの設定例

(例として記事モデル"Article"に対するコメント"Comment"が一覧がくっついてくるような出力を実装するとします)

  • 親モデル(アプリ名articleとします)
#article.models.py

class Article(models.Model):
    title = models.CharField(max_length=300, blank=True, null=True)
    cotents_text = models.TextField(blank=True, null=True)
    pubdate = models.DateTimeField(auto_now_add=True)
  • 子モデル(親モデルをForeignKeyにしている。アプリ名commentとします)
#comment.models.py

class Comment(models.Model):
    target_article = models.ForeignKey(Article, on_delete=models.SET_NULL)
    comment = models.TextField(blank=True, null=True)
    pubdate = models.DateTimeField(auto_now_add=True)

###Serializerの設定例

comment.models.pyのCommentモデルのserializerをつくっておきます。

#comment.api.serializers.py

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

ここからが山場です

article.models.pyのArticleモデルのserializerをつくっておきます。

#article.api.serializers.py


from rest_framework.serializers import SerializerMethodField

from article.models import *
from comment.models import *
from comment.api.serializers import * 
#↑のインポートを忘れずに^^

class ArticleDetailSerializer(ModelSerializer):
    comments = SerializerMethodField() #このフィールドを加えると下記のように出力する値を操作できます。
    class Meta:
        model = Article
        fields = [
            'id',
            'title',
            'cotents_text',
            'pubdate',
            'comments', #モデルには存在しない追加する新フィールド
        ]

    def get_comments(self, obj):
        try:
            comment_abstruct_contents = CommentChildSerializer(Comment.objects.all().filter(target_article = Article.objects.get(id=obj.id)), many=True).data
            #↑ここを"Comment.objects.all().filter(target_article = Article.objects.get(id=obj.id)"
            #とだけにすると、"Item is not JSON serializable"というエラーが出ますので
            #Serializer(出力させたいもの).data という処理が必要です。
            return comment_abstruct_contents
        except:
            comment_abstruct_contents = None
            return comment_abstruct_contents

つぎにviewsを通常のRetrieveAPIViewとかけばOKです。

#article.api.views.py

from rest_framework.generics import RetrieveAPIView

from article.models import *
from comment.models import *
from comment.api.serializers import * 


class ArticleDetailAPIView(RetrieveAPIView):
    queryset = Article.objects.all()
    serializer_class = ArticleDetailSerializer
    lookup_field = 'pk'

最後にurls.pyを書いて動作確認しましょう。

from django.urls import path
from .views import ArticleDetailAPIView

urlpatterns = [
   path('detail_articles/<int:pk>/', ArticleDetailAPIView.as_view(), name='detail')
]

※引数とpath設定がDjango1系とは異なります

###拡張モジュールも見つけました

DRFのJSON出力を拡張するのにこのモジュールも使えそうですので共有します。(上記の方法ならこのモジュールを使わずとも出力できますが、モジュールの需要もありそうなので共有します^^ ) 

57
50
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
57
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?