Подтвердить что ты не робот

Django Rest Framework - APINiew Pagination

У меня очень простая APIView, но я не знаю, как настроить разбиение на страницы здесь. В этом сценарии я выбираю Event с заданным pk, затем я получаю все NewsItems, назначенные этому Event.

pagination_class = LimitOffsetPagination работает ОК, когда я определяю запрос в начале в ListCreateAPIView, например. queryset = Event.objects.all(), но не с пользовательским get:

class EventNewsItems(APIView):
    pagination_class = LimitOffsetPagination

    def get(self, request, pk, format=None):

        #user = request.user
        event = Event.objects.get(pk=pk)
        news = event.get_news_items().all()

        serializer = NewsItemSerializer(news, many=True, context={'request':request})
        response = Response(serializer.data, status=status.HTTP_200_OK)
        return response

Решено:

def get(self, request, pk, format=None):

    #user = request.user
    event = Event.objects.get(pk=pk)
    news = event.get_news_items().all()
    paginator = LimitOffsetPagination()
    result_page = paginator.paginate_queryset(news, request)
    serializer = NewsItemSerializer(result_page, many=True, context={'request':request})
    response = Response(serializer.data, status=status.HTTP_200_OK)
    return response
4b9b3361

Ответ 1

Я создал пример стиля Q & A на эту тему.
Как краткая сводка:

Используя исходный код Django Rest Frameworks и то, как они обрабатывают нумерацию страниц, мы создаем те же методы внутри нашего класса представления и используем их так же, как ваше решение использует методы по умолчанию:

Взято из вышеупомянутого документа:

from rest_framework.settings import api_settings
from rest_framework.views import APIView

class MyView(APIView):
    queryset = OurModel.objects.all()
    serializer_class = OurModelSerializer
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS # cool trick right? :)

    # We need to override get method to achieve pagination
    def get(self, request):
        ...
        page = self.paginate_queryset(self.queryset)
        if page is not None:
            serializer = self.serializer_class(page, many=True)
            return self.get_paginated_response(serializer.data)

        ... Do other stuff needed (out of scope of pagination)

    # Now add the pagination handlers taken from 
    #  django-rest-framework/rest_framework/generics.py

    @property
    def paginator(self):
        """
        The paginator instance associated with the view, or 'None'.
        """
        if not hasattr(self, '_paginator'):
            if self.pagination_class is None:
                self._paginator = None
            else:
                self._paginator = self.pagination_class()
        return self._paginator

     def paginate_queryset(self, queryset):
         """
         Return a single page of results, or 'None' if pagination is disabled.
         """
         if self.paginator is None:
             return None
         return self.paginator.paginate_queryset(queryset, self.request, view=self)

     def get_paginated_response(self, data):
         """
         Return a paginated style 'Response' object for the given output data.
         """
         assert self.paginator is not None
         return self.paginator.get_paginated_response(data) 

Ответ 2

Другим вариантом будет наследование от класса пагинации с меньшим количеством изменений в классе представления:


class EventNewsItems(APIView, LimitOffsetPagination):

    def get(self, request, pk, format=None):
        event = Event.objects.get(pk=pk)
        news = event.get_news_items().all()

        results = self.paginate_queryset(news, request, view=self)
        serializer = NewsItemSerializer(results, many=True)
        return self.get_paginated_response(serializer.data)