Reputation: 1128
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!
Upvotes: 0
Views: 1448
Reputation: 1506
The project django-rest-framework-json-api recently implemented support for this behavior.
It's used like this:
class UserSerializer(serializers.Serializer):
name = serializers.CharField(max_length=200)
# PostSerializer NOT included directly on the serializer, ResourceRelatedField is
# specified as default
posts = relations.ResourceRelatedField(
source='post_set', many=True, read_only=True)
# specifies serializer to use when passing in the `include` param
included_serializers = {
'posts': PostSerializer,
}
If I understand well, you already implemented part of the JSON-API specification by yourself, so I don't know if it's viable for you to switch things and use their project. But looking on how they implemented what you want may be of some help. See this and this, for example.
Upvotes: 3
Reputation: 2119
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
Upvotes: 0