masanorinyo masanorinyo - 3 months ago 10
Python Question

JSON API with Django Rest - 'included' attribute

I am creating JSON-API using Django-rest framework. I could structure the returned JSON object in the same way as JSON-API documentation specifies, except for "included" attribute. Is there any way to include multiple serialized objects of related-models?

For example

If I have two model classes

# Snippet Model
from django.db import models
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
user = models.ForeignKey('auth.User', related_name='snippets')

# Comment Model
from django.db import models
class Comment(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
user = models.ForeignKey('auth.User', related_name='comments')


and I have the serializers for those two models:

from rest_framework import serializers
class SnippetSerializer(serializers.ModelSerializer):
model = Snippet
fields = ('id','created', 'title')

from rest_framework import serializers
class CommentSerializer(serializers.ModelSerializer):
model = Comment
fields = ('id','created', 'title')


and I have User serializer

# User serializer
from .serializers import SnippetSerializer
from .serializers import CommentSerializer
class UserSerializer(serializers.ModelSerializer):
included = serializers.SerilizerMethodField()
class Meta:
model = User
fields = ('id','included')

def get_included(self, obj):
included_objs = []
request = self.context['request']

# check if requested url has a query parameter "included"
query = request.QUERY_PARAMS['included'] if 'included' in request.QUERY_PARAMS else None
if query:
queries = query.split(',')
if 'included' in queries:
snippets = SnippetSerializer(many=True, read_only=True).data
comments = CommentSerializer(many=True, read_only=True).data
included_objs.append(snippets)
included_objs.append(comments)
return included_objs


and these code didn't give me what I needed.

The objective is that if requested url includes a query "included", then API will return a JSON object with CommentSerialized and SnippetSerialized objects related to user object under 'included' attribute. The result should be something like this.

{
"id" : 1,
"included": [
{'id': 2,'created': "20150729", "title":'snippet' },
{'id': 2,'created': "20150730", "title":"comment" },
{'id': 3,'created': "20150731", "title":"comment" },
]
}


It would be wonderful if someone can help me out here. Thanks!

Answer

For this I would write a second serializer:

class IncludedUserSerializer(serializers.ModelSerializer):
      snippets = SnippetSerializer(source = 'snippet_set', many=True)
      comments = CommentSerializer(source = 'comment_set', many=True)

      class Meta:
          model=User
          fields = ('id','snippets', 'comments')

Then in your view override the get_serializer method

 def get_serializer(self):
     if self.query_params.get('included', None):
           return IncludedUserSerializer
     else:
           return UserSerializer
Comments