python - 在这种情况下如何应用分页(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 带有一个内置的分页器中间件。您只需将这些行添加到 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 设置似乎更合理。
推荐阅读
- ibm-watson - 如何在 ibm watson 语音到文本的 android sdk 中使用 audiofilewritter?
- cordova - 使用cordova获取设备令牌(iphone)并实现推送通知
- php - Laravel 两种 404 样式
- python - 与报价处理完全混淆
- r - 如何一起显示来自visNetwork的节点和边的闪亮输入而不是单独显示
- javascript - 如果我更改端点,中间件将不起作用
- javascript - 如果视频正在加载(缓冲),则显示带有加载 GIF 图像的 HTML5 视频
- javascript - 检查对象中是否已存在对象
- python - 使用 Python 查找 DLL 的绝对路径时出现问题 - pefile、win32api、win32con、wintypes、windll
- android - 如何检查 Android 服务是否已在运行