You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django REST Framework中实现支持动态分页与django_filters兼容的API

Django REST Framework 动态分页兼容 django_filters 实现方案

核心思路

  • 自定义分页类,根据请求中是否存在offset/limit参数决定是否启用分页
  • 与django_filters结合时复用过滤后的QuerySet,避免重复执行SQL查询
  • 用exists()高效判断是否存在下一页,替代性能较差的count()

自定义动态分页类

from rest_framework.pagination import BasePagination
from rest_framework.response import Response

class DynamicOffsetPagination(BasePagination):
    def paginate_queryset(self, queryset, request, view=None):
        # 获取分页参数,无参数则不启用分页
        offset = request.query_params.get('offset')
        limit = request.query_params.get('limit')
        
        if offset is None or limit is None:
            return None
        
        try:
            offset = int(offset)
            limit = int(limit)
            if offset < 0 or limit <= 0:
                raise ValueError
        except (ValueError, TypeError):
            # 参数不合法时返回全量数据
            return None
        
        end = offset + limit
        self.current_offset = offset
        self.current_limit = limit
        # 仅查询下一页是否存在单条数据,避免全表count
        self.has_next = queryset[end:end+1].exists()
        
        return queryset[offset:end]
    
    def get_paginated_response(self, data):
        return Response({
            'offset': self.current_offset,
            'limit': self.current_limit,
            'has_next': self.has_next,
            'results': data
        })

与django_filters结合的视图实现

假设你有模型Book、序列化器BookSerializer和过滤器BookFilter:

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
from .filters import BookFilter

class BookViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = BookFilter
    pagination_class = DynamicOffsetPagination

关键细节说明

  1. SQL请求优化:分页逻辑复用视图过滤后的QuerySet,exists()仅执行单条数据查询,避免全表count带来的性能损耗
  2. 参数容错:对offset和limit做类型与范围校验,非法参数自动返回全量数据
  3. 动态切换:仅当同时提供offset和limit时启用分页,无参数时直接返回所有结果

使用示例

  • 分页请求:GET /api/books?offset=0&limit=10
    返回结构:
    {
      "offset": 0,
      "limit": 10,
      "has_next": true,
      "results": [...]
    }
    
  • 全量请求:GET /api/books
    返回结构:
    [...]
    

内容的提问来源于stack exchange,提问作者Chanchhunneng chrea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 15:42:11