Как добавить дополнительное поле в Django REST Framwork Serializer GET return - PullRequest
0 голосов
/ 21 января 2020

Я хочу добавить дополнительную статистику в рабочий сериализатор для Django REST framework: если я делаю GET-запрос для нескольких случаев, я хочу вернуть не только случаи, но и статистику c о случаях, соответствующих Запрос (без нумерации страниц):

Запрос:

GET /api/cases/?page=1&gender=0

Мне нужно вернуть все соответствующие случаи с разбивкой на страницы, но добавить статистику по всем соответствующим (в данном случае всем женщинам) случаям:

{
    "count": 10593,
    "next": "http://localhost:8000/api/adrcases/?page=2",
    "previous": null,
    "stats": {
             "age_mean": 32.212,
             "age_sd": 6.12,
             ...
              }

    "results": [
        {
            "code": "case_001",
            "age": 47,
             ...

Как я могу изменить свой сериализатор, добавив дополнительное поле, например поле статистики, показанное выше?

class CaseSerializer(serializers.ModelSerializer):

    class Meta:
        model = Case
        fields = "__all__"

    def update(self, instance, validated_data):
        ...



    def create(self, validated_data):
        ...

Ответы [ 3 ]

3 голосов
/ 21 января 2020

Вы можете использовать пользовательскую нумерацию страниц

from rest_framework.pagination import PageNumberPagination

class CustomPagination(PageNumberPagination):
page_size = 20
# page_size = 2
page_size_query_param = 'page_size'
max_page_size = 1000

def get_paginated_response(self, data):
    return Response({
        'links': {
            'next': self.get_next_link(),
            'previous': self.get_previous_link()
        },
        'stats': {
            'age_mean': 32.212,
            'age_sd': 6.12
        }
        'results': data
    })

Затем добавьте этот класс в ваше представление:

class MyAPIView(APIView):
    pagination_class = CustomPagination

для получения дополнительной информации см. custom-pagination-styles .

1 голос
/ 21 января 2020

Ответ обновлен

Здесь вы можете переопределить свой метод ListAPIView.list и легко вставить в него свои данные

# inside views.py
class CaseListAPI(ListAPIView):
    serializer_class = CaseSerializer
    queryset = Case.objects.all()
    pagination_class = PageNumberPagination

    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)
        self._inject_case_stats(response)
        return response

    def _inject_case_stats(self, response):
        # Here you can calculate your data and inject it to response
        all_cases_count = self.queryset.count()
        # you can use self.filter_queryset() to get the filtered result and do the aggregation to get age sum.
        filtered_age_sum = self.filter_queryset(self.get_queryset()).aggregate(Sum('age'))['age__sum']
        all_age_sum = self.queryset.aggregate(Sum('age'))['age__sum']
        all_age_mean = all_age_sum / all_cases_count
        # And now you can calculate the mean for the filtered results.
        filtered_age_mean = filtered_age_sum / all_cases_count
        response.data['stats'] = {
            'age_mean': age_mean,
            'filtered_age_mean': filtered_age_mean
        }

Обновитель ответа: я добавил логи c рассчитать среднее всех отфильтрованных результатов (без разбивки на страницы) только на счетчик всех записей.

1 голос
/ 21 января 2020

Это просто концепция. Вы должны изменить этот код так, как вам нравится

class Ser1(serializers.ModelSerializer):
    class Meta:
        model = Stats
        fields = ('age_mean', 'age_sd',)


class Ser2(serializers.ModelSerializer):
    class Meta:
        model = Case
        fields = ('__all__')


class MainSer(serializers.Serializer):
    ser1 = Ser1()
    ser2 = Ser2(many=True)
    class Meta:
        fields = ('ser1', 'ser2',)
...