繁体   English   中英

将额外数据添加到整个结果集的 Django Rest Framework 结果

[英]Adding extra data to Django Rest Framework results for entire result set

我正在使用 Django Rest Framework,需要向结果集添加额外的数据。 具体来说,您通常会拥有:

{
    "count": 45, 
    "next": "http://localhost:8000/foo/bar?page=2", 
    "previous": null, 
    "results": [
        {...}
    ]
}

我想添加额外的计数,如下所示:

{
    "count": 45,
    "10_mi_count": 10,
    "20_mi_count": 30,
    "30_mi_count": 45,
    "next": "http://localhost:8000/foo/bar?page=2", 
    "previous": null, 
    "results": [
        {...}
    ]
}

此示例中的额外计数只是具有字段距离值小于键中描述的英里数的对象数量。

我的问题是我不知道扩展和插入此行为的最佳位置在哪里。

理想情况下,无论结果是否分页,我都希望它能够工作,不做任何假设。

我真正追求的是朝着正确的方向点头(以及为什么这是正确的地方)。

我已经检查了文档,但找不到任何描述如何添加此类内容的内容,但我很乐意在该分数上被证明是错误的。

由于您似乎正在使用 Rest Framework 中的 ListViews 之一,您可以覆盖类中的 list() 方法并在结果数据上设置新值,如下所示:

    def list(self, request, *args, **kwargs):
        response = super().list(request, args, kwargs)
        # Add data to response.data Example for your object:
        response.data['10_mi_count'] = 10 # Or wherever you get this values from
        response.data['20_mi_count'] = 30
        response.data['30_mi_count'] = 45
        return response

请注意,您的类必须直接或通过 Rest Framework API ( http://www.django-rest-framework.org/api-guide/generic-views#listmodelmixin ) 中的 GenericView 继承 ListModelMixin。 我真的不知道这样做是否正确,但这是一个快速解决方案。

希望能帮助到你!

使用本解决方案中提到的SerializerMethodField

它可用于将任何类型的数据添加到对象的序列化表示中。 REST 框架文档

文档中的示例:

from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    days_since_joined = serializers.SerializerMethodField()

    class Meta:
        model = User

    def get_days_since_joined(self, obj):
        return (now() - obj.date_joined).days

最后,我刚刚创建了一个自定义分页序列化程序,其字段如下:

class DistanceCountField(serializers.Field):
    def to_native(self, value):
        try:
            distance_counts = {
                '1_mile': self._count_lte_miles(value, 1),
                '5_mile': self._count_lte_miles(value, 5),
                '10_mile': self._count_lte_miles(value, 10),
                '20_mile': self._count_lte_miles(value, 20),
            }
        except FieldError:
            distance_counts = None

        return distance_counts

    def _count_lte_miles(self, value, miles):
        meters = miles * 1609.344
        return value.filter(distance__lte=meters).count()


class PaginatedCountSerializer(pagination.PaginationSerializer):
    distance_counts = DistanceCountField(source='paginator.object_list')

    class Meta:
        # Class omitted, just a standard model serializer
        object_serializer_class = MyModelSerializer 

我还为查询集中的每个对象添加了一个距离注释,以便进行过滤。

我也将 DRF 与分页一起使用,并希望添加返回的查询集本身的摘要,因此首先我必须在列表方法中获取查询集。

def list(self, request, *args, **kwargs):
    queryset = self.filter_queryset(self.get_queryset())
    summary = {}
    summary['x'] = queryset.filter(transaction_type='x').count()
    summary['y'] = queryset.filter(transaction_type='y').count()

    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        data = {}
        data['summary'] = summary
        data['details'] = serializer.data
        return self.get_paginated_response(data)


    serializer = self.get_serializer(queryset, many=True)
    data = {}
    data['summary'] = summary
    data['details'] = serializer.data
    return Response(data)

这给了我以下答复:

{
  "count": 20,
  "next": "http://..",
  "previous": null,
  "results": {
    "summary": {
      "x": 15,
      "y": 5,
    },
    "details": [
      {.....

注意:这也适用于非分页结果。

我在这里捎带接受的答案!

我认为主要问题是序列化程序返回一个 ReturnList,它只是一个带有一些额外上下文的常规列表。

您可以像这样用自己的 OrderedDict 替换数据:

response = super().list(request, *args, **kwargs)
new_data = OrderedDict()
new_data.update({
    'results': response.data,
    '10-mi-count': 10,
    #etc...
})
response.data = new_data

return response 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM