Добавление дополнительных данных в результаты Django Rest Framework для всего набора результатов
Я использую 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": [
{...}
]
}
Дополнительные подсчеты в этом примере - это только то, сколько объектов имеет полевое расстояние со значением, меньшим миль, описанных в ключе.
Моя проблема в том, что я понятия не имею, где лучшее место для расширения и вставки этого поведения.
В идеале, мне бы хотелось, чтобы это работало независимо от того, были ли страницы разбиты на страницы или нет, не допуская никаких предположений.
То, что я на самом деле после этого, - это кивка в правильном направлении (и почему это подходящее место для него).
Я проверил документы и не могу найти ничего, что описывает, как добавлять такие вещи, но я был бы более чем счастлив, если бы оказался ошибочным на этот счет.
Ответы
Ответ 1
Поскольку вы, похоже, используете один из ListViews из Rest Framework, вы можете переопределить метод 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
Обратите внимание, что ваш класс должен наследовать ListModelMixin напрямую или через GenericView из API Rest Framework (http://www.django-rest-framework.org/api-guide/generic-views#listmodelmixin). Я действительно не знаю, правильно ли это делать, но это быстрое решение.
Надеюсь, поможет!
Ответ 2
Используйте SerializerMethodField, как указано в этом решении.
Его можно использовать для добавления любых данных в сериализованное представление вашего объекта. (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
В конце концов, я просто создал настраиваемый сериализатор разбиения на страницы с таким полем:
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
Я также добавил аннотацию расстояния к каждому объекту в наборе запросов для работы фильтрации.