我使用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": [
{...}
]
}
此示例中的额外计数只是有多少对象的字段距离,其值小于密钥中描述的英里数。
我的问题是我不知道扩展和插入此行为的最佳位置在哪里。
理想情况下,无论结果是否分页,我都希望这项工作正常工作,不做任何假设。
我真正想到的是朝着正确的方向点头(为什么这是正确的地方)。
我已经检查了文档,无法找到任何描述如何添加此类内容的内容,但我很高兴在该分数上被证明是错误的。
答案 0 :(得分:29)
由于您似乎正在使用Rest Framework中的一个ListView,您可以覆盖类中的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。我真的不知道这是否是正确的方法,但这是一个快速修复。
希望它有所帮助!
答案 1 :(得分:4)
最后我创建了一个自定义分页序列化程序,其字段如下:
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
我还为查询集中的每个对象添加了距离注释,以便进行过滤。
答案 2 :(得分:3)
使用SerializerMethodField中提到的solution。
它可用于将任何类型的数据添加到对象的序列化表示中。 (REST framework doc)
文档中的示例:
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
答案 3 :(得分:1)
我也将DRF与分页一起使用,并且想添加返回的查询集本身的摘要,因此首先我必须在list方法中获取queryset。
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": [
{.....
注意:这也适用于非分页结果。
答案 4 :(得分:1)
我在这里附上接受的答案!
我认为主要问题是序列化程序返回一个 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