如何在Json中返回带有额外字段的对象列表(Django Rest Framework)

时间:2016-02-28 00:16:44

标签: django rest django-rest-framework

我正在使用ModelViewSet通过get_queryset生成项目列表。我想返回一个json,其中包含对象列表和一个额外的字段(DurationField的总时间)。 例如:

{  
   "total_time":"00:10:00",
   "objects":[  
      {  
         "pk":1,
         "title":"Title",
         "duration": "00:05:00"
      },
      {  
         "pk":1,
         "title":"Title",
         "duration": "00:05:00"
      }
   ]
}

我该怎么做?这是我的代码。

ModelViewSet:

class ModelViewSet(viewsets.ModelViewSet):
    queryset = Model.objects.all()
        serializer_class = ModelSerializer
        permission_classes = (IsAuthenticated,)

        def get_queryset(self):
            user = self.request.user
            list = Model.objects.filter(user=user)
            total_time = .. ## sum the duration of list of objects

            ## I want to return the list and total_time
            return list

serializers.py:

class ModelSerializer(serializers.ModelSerializer):
            pk = serializers.IntegerField(read_only=True)
            user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), required=False, allow_null=True)
            project = serializers.PrimaryKeyRelatedField(queryset=Project.objects.all(), required=False, allow_null=True)
            class Meta:
                model = Model

                fields = ('pk', 'title', 'user', 'project', 'duration')

网址:

router = DefaultRouter()
router.register(r'^', views.ModelViewSet)
urlpatterns = [
    url(r'^api', include(router.urls)),
]

2 个答案:

答案 0 :(得分:1)

一种方法是将paginator子类化(默认的分页类为PageNumberPagination)并调整get_paginated_response。这完全未经测试,但可能是这样的:

from rest_framework.pagination import PageNumberPagination

class CustomPageNumberPagination(PageNumberPagination):

    def get_paginated_response(self, data, total_time):
        return Response(OrderedDict([
            ('count', self.page.paginator.count),
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('total_time', total_time),
            ('results', data)
        ]))


class ModelViewSet(viewsets.ModelViewSet):
    queryset = Model.objects.all()
    serializer_class = ModelSerializer
    permission_classes = (IsAuthenticated,)
    pagination_class = CustomPageNumberPagination

    def get_queryset(self):
        user = self.request.user
        list = Model.objects.filter(user=user)

        self.total_time = .. ## sum the duration of list of objects

        return list

    def get_paginated_response(self, data):
        return self.paginator.get_paginated_response(data, self.total_time)

无论如何,希望这有点帮助。

祝你好运!

答案 1 :(得分:0)

最后我做到了!但我不确定这是不是最好的做法。如果有人有更好的想法,请分享!

class ModelJSONRenderer(JSONRenderer):
    """
    Add "objects" and "total_time" in Json
    """
    def render(self, data, accepted_media_type=None, renderer_context=None):
        data = {'objects': data, 'total_time': renderer_context['total_time']}
        return super(ModelJSONRenderer, self).render(data, accepted_media_type, renderer_context)

ModelViewSet:

class ModelViewSet(viewsets.ModelViewSet):
    queryset = Model.objects.all()
        serializer_class = ModelSerializer
        permission_classes = (IsAuthenticated,)
    renderer_classes = (ModelJSONRenderer, )

    def get_queryset(self):
        user = self.request.user
        list = Model.objects.filter(user=user)

        self.total_time = .. ## sum the duration of list of objects

        return list

    def get_renderer_context(self):
        """
        Returns a dict that is passed through to Renderer.render(),
        as the `renderer_context` keyword argument.
        """
        return {
            'view': self,
            'args': getattr(self, 'args', ()),
            'kwargs': getattr(self, 'kwargs', {}),
            'request': getattr(self, 'request', None),
            'total_time': self.total_time
        }