嵌套序列化程序

时间:2016-01-30 23:21:48

标签: django django-rest-framework serializer

我正在使用Django Rest Framework 3.3.2和Django 1.9.1 我有2个序列化器,我在另一个中使用其中一个。

class VideoSerializer(serializers.ModelSerializer):
current_username = serializers.SerializerMethodField()
is_deletable = serializers.SerializerMethodField()
tagged_users = EachUserSerializer(many=True, read_only=True)
print current_username
comments = CommentSerializer(many=True, read_only=True, context={'current_username': current_username})
place_taken = PlaceLimitedSerializer()
owner_user = EachUserSerializer()

class Meta:
    model = Video
    fields = ('tagged_users', 'comments', 'place_taken', 'video_id', 'video_url', 'like_count', 'caption', 'date',
              'category', 'owner_user', 'current_username', 'is_deletable', )

def get_current_username(self, obj):
    self.current_username = self.context['request'].user.username
    return self.context['request'].user.username

def get_is_deletable(self, obj):

    return obj.is_deletable_by(self.current_username)



class CommentSerializer(serializers.ModelSerializer):
current_username = serializers.SerializerMethodField()
is_deletable = serializers.SerializerMethodField()
is_editable = serializers.SerializerMethodField()

def get_current_username(self, obj):
    self.current_username = self.context['current_username']
    return self.current_username

def get_is_deletable(self, obj):
    return obj.is_deletable(self.current_username)

def get_is_editable(self, obj):
    return obj.is_editable(self.current_username)

class Meta:
    model = Comment
    fields = ('comment', 'username', 'comment_id', 'date', 'current_username', 'is_editable', 'is_deletable',)

我的问题是我需要序列化程序中当前用户的用户名。我设法通过在视图中设置上下文来在VideoSerializer中执行此操作。

class get_video(APIView):

def get(self, request):
    video_id = str(request.query_params.get('video_id'))
    if Video.objects.all().filter(video_id=video_id).exists():
        video = Video.objects.get(video_id=video_id)
        serializer = VideoSerializer(video, context={"request": request})
        return JsonResponse(serializer.data)
    else:
        return JsonResponse({"result": "no_video"})

在VideoSerializer中,我尝试设置上下文,我想将'current_user'传递给CommentSerializer,但它会出现此错误。

Internal Server Error: /video/get_video/
Traceback (most recent call last):
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/mcagataybarin/molocate-dev/molocate_eb/video/views.py", line 96, in get
return JsonResponse(serializer.data)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 503, in data
ret = super(Serializer, self).data
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 239, in data
self._data = self.to_representation(self.instance)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 472, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 614, in to_representation
self.child.to_representation(item) for item in iterable
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 472, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/fields.py", line 1645, in to_representation
return method(value)
File "/Users/mcagataybarin/molocate-dev/molocate_eb/video/serializers.py", line 13, in get_current_username
self.current_username = self.context['current_username']
KeyError: 'current_username'

我该如何解决?我检查了DRF文档并检查了stackoverflow但找不到正确的答案。如果你帮忙,我会很感激。

2 个答案:

答案 0 :(得分:1)

context可用于顶级序列化程序下的任何内容 - 即也适用于序列化程序和字段。 因此,在CommentSerializer中你应该有:

self.current_username = self.context['request'].user.username

答案 1 :(得分:1)

经过大量的谷歌搜索后,我解决了这个问题。

class VideoSerializer(serializers.ModelSerializer):
current_username = serializers.SerializerMethodField()
is_deletable = serializers.SerializerMethodField()
tagged_users = EachUserSerializer(many=True, read_only=True)
comments = serializers.SerializerMethodField()
place_taken = PlaceLimitedSerializer()
owner_user = EachUserSerializer()

class Meta:
    model = Video
    field = ('tagged_users', 'comments', 'place_taken', 'video_id', 'video_url', 'like_count', 'caption', 'date',
              'category', 'owner_user', 'is_deletable', )

def get_comments(self, obj):
    serializer_context = {'current_username': self.current_username}
    serializer = CommentSerializer(obj.comments, many=True, read_only=True, context=serializer_context)
    return serializer.data

def get_current_username(self, obj):
    self.current_username = self.context['request'].user.username
    return self.context['request'].user.username

def get_is_deletable(self, obj):

    return obj.is_deletable_by(self.current_username)

class CommentSerializer(serializers.ModelSerializer):
current_username = serializers.SerializerMethodField()
is_deletable = serializers.SerializerMethodField()
is_editable = serializers.SerializerMethodField()

def get_current_username(self, obj):
    self.current_username = self.context.get('current_username')
    return self.context.get('current_username')

def get_is_deletable(self, obj):
    return obj.is_deletable(self.current_username)

def get_is_editable(self, obj):
    return obj.is_editable(self.current_username)

class Meta:
    model = Comment
    fields = ('comment', 'username', 'comment_id', 'date', 'current_username', 'is_editable', 'is_deletable',)

我在SerializerMethodField中序列化了嵌套序列化,并且我将从上下文中提取的current_username发送到了nester序列化程序的上下文。在这个问题解决后,它的工作原理:)