如何在DRF视图中根据评论ID跳转到对应分页页面?
Django通用视图实现带comment_id参数跳转到对应分页页面的方案
核心问题分析
你之前的错误在于在get_queryset方法中处理跳转逻辑,这个方法的职责是返回查询集,不能返回URL或响应对象,必须在请求处理的方法(比如get)中处理重定向或参数修改。
方案一:重定向到目标分页URL
这种方式会让浏览器跳转到带正确分页参数的URL,用户地址栏会更新为目标分页地址。
步骤1:配置分页类
先定义符合你需求的分页类(和代码中的page_size保持一致):
from rest_framework.pagination import PageNumberPagination class CommentPagination(PageNumberPagination): page_size = 10 # 与你计算时用的每页数量一致
步骤2:修改视图类逻辑
重写get方法处理参数判断与重定向,get_queryset只负责过滤查询集:
from django.shortcuts import redirect from django.urls import reverse from rest_framework import generics, permissions from .models import Comment from .serializers import CommentSerializer class CommentList(generics.ListCreateAPIView): permission_classes = [permissions.AllowAny] queryset = Comment.objects.all() serializer_class = CommentSerializer pagination_class = CommentPagination # 绑定分页类 def get(self, request, *args, **kwargs): comment_id = request.GET.get('comment_id') thread_id = request.GET.get('thread') # 仅当同时存在comment_id和thread参数时处理跳转 if comment_id and thread_id: try: # 验证评论是否存在于当前thread Comment.objects.get(id=comment_id, thread=thread_id) except Comment.DoesNotExist: # 评论不存在,直接返回正常列表 return super().get(request, *args, **kwargs) # 计算评论所在页码 num_preceeding = Comment.objects.filter(thread=thread_id, id__lt=comment_id).count() page_size = self.pagination_class.page_size page_num = num_preceeding // page_size + 1 # 构建重定向URL,使用DRF默认的page分页参数 redirect_url = f"{reverse('comment-view')}?thread={thread_id}&page={page_num}" return redirect(redirect_url) # 无comment_id参数时,正常处理列表请求 return super().get(request, *args, **kwargs) def get_queryset(self): thread_id = self.request.GET.get('thread') if thread_id: return Comment.objects.filter(thread=thread_id) return super().get_queryset()
方案二:直接返回目标分页结果(无需重定向)
如果不想让用户地址栏变化,可直接修改请求的分页参数,返回目标页内容:
from rest_framework import generics, permissions from .models import Comment from .serializers import CommentSerializer class CommentList(generics.ListCreateAPIView): permission_classes = [permissions.AllowAny] queryset = Comment.objects.all() serializer_class = CommentSerializer pagination_class = CommentPagination def get(self, request, *args, **kwargs): comment_id = request.GET.get('comment_id') thread_id = request.GET.get('thread') if comment_id and thread_id: try: Comment.objects.get(id=comment_id, thread=thread_id) except Comment.DoesNotExist: return super().get(request, *args, **kwargs) num_preceeding = Comment.objects.filter(thread=thread_id, id__lt=comment_id).count() page_size = self.pagination_class.page_size page_num = num_preceeding // page_size + 1 # 复制并修改GET参数,替换为page参数,移除comment_id避免循环 request.GET = request.GET.copy() request.GET['page'] = str(page_num) request.GET.pop('comment_id', None) return super().get(request, *args, **kwargs) def get_queryset(self): thread_id = self.request.GET.get('thread') if thread_id: return Comment.objects.filter(thread=thread_id) return super().get_queryset()
内容的提问来源于stack exchange,提问作者Mulham
相关产品推荐
相关产品推荐

