【问题标题】:How to return a list of objects with an extra field in Json (Django Rest Framework)如何在 Json 中返回带有额外字段的对象列表(Django Rest Framework)
【发布时间】:2016-02-28 00:16:44
【问题描述】:

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

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

我该怎么做?下面是我的代码。

模型视图集:

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)),
]

【问题讨论】:

    标签: django rest django-rest-framework


    【解决方案1】:

    一种方法是对分页器进行子类化(默认分页类是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)
    

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

    祝你好运!

    【讨论】:

    • 感谢@CaffeineFueled!但我不知道这是否是最佳做法!我不这样做,如果您能告诉我您对代码的看法,我将不胜感激!
    【解决方案2】:

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

    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)
    

    模型视图集:

    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
            }
    

    【讨论】:

    • 我不确定在这种情况下是否存在“最佳实践”之类的东西。如果您找到适合您的东西并且它不是非常复杂和/或无法维护,那么我说运行它。可悲的是,我目前无法使用您的解决方案,但我认为这个概念看起来很合理。干杯!
    • 再次感谢@CaffeineFueled ;)
    猜你喜欢
    • 2022-08-08
    • 2015-01-20
    • 1970-01-01
    • 2020-06-22
    • 2015-09-01
    • 2018-07-01
    • 2015-03-15
    • 2019-08-19
    • 2021-08-20
    相关资源
    最近更新 更多