【问题标题】:How to apply pagination in this case (Django Rest Framework)?在这种情况下如何应用分页(Django Rest Framework)?
【发布时间】:2021-08-16 11:50:34
【问题描述】:

我构建了一个简单的社交媒体应用程序。用户可以发布两种类型的帖子博客和轮播。用户可以关注其他用户,关注后可以看到其他用户的帖子。

因此,在实现主页 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)

【问题讨论】:

  • 所以你想对博客和轮播的组合进行分页,对吧?它将使用哪种排序方式?还是您想获得博客的前 10 个和轮播的前 10 个并返回 20 个项目?

标签: python django django-rest-framework


【解决方案1】:

DRF 带有一个内置的paginator middleware。您只需将这些行添加到 settings.py

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

如果你想用不同的PAGE_SIZE对每个资源进行分页,Django核心有一个内置的分页器类用于各种模型对象 应该是这样的:首先你 order_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 设置似乎更合理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    相关资源
    最近更新 更多