Как применить пагинацию в этом случае (Django Rest Framework)?

Я создал простое приложение для социальных сетей. Пользователи могут публиковать два типа постов Блог и Карусель. Пользователи могут следовать за другими пользователями, вы можете видеть посты других пользователей, если вы следуете за ними.

Итак, при реализации API домашней страницы (домашняя страница состоит из блога и карусели постов людей, за которыми вы следите) я отфильтровываю блог и карусель следующим образом.

blogposts = BlogPost.objects.filter(
            Q(author__profile__in=request.user.profile.followings.all())
            | Q(author=request.user)
        )

carouselposts = Carousel.objects.filter(
            Q(author__profile__in=request.user.profile.followings.all())
            | Q(author=request.user)
        )

По сути, он фильтрует все блоги и карусели людей, за которыми вы следите, и возвращает их после применения соответствующих сериализаторов.

Но проблема в том, что при загрузке страницы, если пользователь имеет 100 сообщений на своей домашней странице, все они загружаются сразу. Вместо этого я хочу загрузить только 10 последних сообщений в начале и продолжать загружать следующие 10 последних сообщений, когда пользователь достигнет нижней части домашней страницы.

Поскольку здесь есть две таблицы Blogpost и Carousel, я не знаю, как сделать пагинацию.

Кроме того, еще один вопрос? Если я каким-то образом распишу это содержимое на страницы, чтобы отправить 10 последних сообщений сразу, будет ли он внутренне запрашивать только 10 сообщений при каждом запросе или он будет запрашивать все 100 сообщений сразу и отправлять их частями по 10?

Вот полный код для API домашней страницы.


class HomepageBlogPostView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):

        blogposts = BlogPost.objects.filter(
            Q(author__profile__in=request.user.profile.followings.all())
            | Q(author=request.user)
        )
        posts_list_serializer = BlogPostSerializer(
            blogposts, many=True, context={"request": request}
        )

        carouselposts = Carousel.objects.filter(
            Q(author__profile__in=request.user.profile.followings.all())
            | Q(author=request.user)
        )

        carousels_list_serializer = CarouselSerializer(
            carouselposts, many=True, context={"request": request}
        )

        blogposts_list = list(posts_list_serializer.data)
        carousels_list = list(carousels_list_serializer.data)

        blogposts_list.extend(carousels_list)
        posts = blogposts_list
        posts.sort(key=lambda post: -post["published"])

        return Response(posts, status=status.HTTP_200_OK)

DRF поставляется со встроенным промежуточным ПО paginator middleware. Вам просто нужно добавить эти строки в settings.py

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10 # default value is 100
}

если вы хотите помещать в пагинацию каждый ресурс с разным PAGE_SIZE, в ядре Django есть встроенный класс paginator для всех видов объектов Model. Это будет выглядеть примерно так: сначала вы упорядочиваете_by("-created_at"), затем используете класс Paginator.

from django.core.paginator import Paginator

class HomepageBlogPostView(APIView):
     permission_classes = [permissions.IsAuthenticated]

    def get_nth_page(self , n):
        PAGE_SIZE = 10 # or just define it inside settings.py

        blogposts = BlogPost.objects.filter(
           Q(author__profile__in=request.user.profile.followings.all())
            | Q(author=request.user)
        ).order_by('-created_at')
        paginated = Paginator(blogposts,PAGE_SIZE )
        return paginated.page(n).object_list

def get(self, request):
        # return page number or 1
        blogposts = self.get_nth_page(request.GET('page_number',1)) 
        
            posts_list_serializer = BlogPostSerializer(
            blogposts, many=True, context={"request": request}
        )

        carouselposts = Carousel.objects.filter(
            Q(author__profile__in=request.user.profile.followings.all())
            | Q(author=request.user)
        )

        carousels_list_serializer = CarouselSerializer(
            carouselposts, many=True, context={"request": request}
        )

        blogposts_list = list(posts_list_serializer.data)
        carousels_list = list(carousels_list_serializer.data)

        blogposts_list.extend(carousels_list)
        posts = blogposts_list
        posts.sort(key=lambda post: -post["published"])

        return Response(posts, status=status.HTTP_200_OK)

для поддержания PAGE_SIZE одинаковым для всех ресурсов, использование настройки DRF кажется более разумным.

Вернуться на верх