drf - 偏移分页组件 LimitOffsetPagination

目录

  • 数据准备
  • 分页组件部分源码分析一
  • 自定义分页组件
  • 分页组件部分源码分析二

数据准备

model.py文件

定义两个表Car表和Brand表,其中Car中的brand字段外键关联Brand表

from django.db import models
class BaseModel(models.Model):
    is_delete = models.BooleanField(default=False)
    create_time = models.DateTimeField(auto_now_add=True)
    class Meta:
        abstract = True

class Car(BaseModel):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    brand = models.ForeignKey('Brand', db_constraint=False, on_delete=models.DO_NOTHING, related_name='cars')
    @property
    def brand_name(self):
        return self.brand.name
    class Meta:
        db_table = 'old_boy_car'
        verbose_name = '汽车'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.name

class Brand(BaseModel):
    name = models.CharField(max_length=32)
    class Meta:
        db_table = 'old_boy_brand'
        verbose_name = '品牌'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.name

新建的serializer.py文件

brand字段只参与反序列化,brand_name只参与序列化

from rest_framework.serializers import ModelSerializer
from . import models
class CarModelSerializer(ModelSerializer):
    class Meta:
        model = models.Car
        fields = ('name','price','brand','brand_name')
        extra_kwargs = {
            "brand":{
                'write_only':True
            },
            'brand_name':{
                'read_only':True
            },
        }

分页组件部分源码分析一

通常是在获取多条数据list方法中,进行分页显示。所以viewsets.py文件中list方法是分页入口

class ListModelMixin:
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())  # 先筛选

        page = self.paginate_queryset(queryset)  # 后分页,再序列化显示
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

1. 先调用paginate_queryset方法,此方法继承至generics中的GenericAPIView类

def paginate_queryset(self, queryset):
    """
    Return a single page of results, or `None` if pagination is disabled.
    """
    if self.paginator is None:  # self.paginator分页器,如果为None表示不分页
        return None
    return self.paginator.paginate_queryset(queryset, self.request, view=self)

2. 调用paginator方法

@property
def paginator(self):
    """
    The paginator instance associated with the view, or `None`.
    """
    if not hasattr(self, '_paginator'):
        # 如果配置中的pagination_class为空就不分页,所以要分页就需要配置pagination_class类,else中实例化分页类
        if self.pagination_class is None:
            self._paginator = None
        else:
            self._paginator = self.pagination_class()
    return self._paginator

3. 自定义pagination_class

4. 调用pagination_class类中的paginate_queryset方法

?

自定义分页组件

新建的paginations.py文件,CarPageNumberPagination继承了drf分页组件中的PageNumberPagination类

from rest_framework.pagination import LimitOffsetPagination
class CarLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3  # 设置每页显示的数量为3,此时url中下一页的offset就会往后偏移3条

    # 优先使用limit_query_param来设置显示条数
    limit_query_param = 'limit'
    offset_query_param = 'offset'  # 偏移数,就是多少条数据后显示
    max_limit = 5

# url链接:car/?limit=2  一页显示2条,默认显示第一页
# url链接:car/?limit=2&offset=4  往后偏移4条数据后,再显示自定义的2条数据,limit输入的数不能大于max_limit设置的数,大于则按max_limit来显示

注意:car/?limit=2&offset=4,若数据总条数只有5条,偏移offset=4条后显示就只显示1条数据

view.py文件:需要自定义pagination_class

from rest_framework.viewsets import ModelViewSet
from . import models, serializer
from .paginations import CarLimitOffsetPagination

class CarModelViewSet(ModelViewSet):
    queryset = models.Car.objects.filter(is_delete=False)
    serializer_class = serializer.CarModelSerializer
    # 自定义pagination_class
    parser_classes = CarLimitOffsetPagination

分页组件部分源码分析二

1. 调用CarLimitOffsetPagination的paginate_queryset方法(继承至LimitOffsetPagination)

def paginate_queryset(self, queryset, request, view=None):
    self.count = self.get_count(queryset)  # 获取数据的总数量
    self.limit = self.get_limit(request)
    if self.limit is None:
        return None

    self.offset = self.get_offset(request)
    self.request = request
    if self.count > self.limit and self.template is not None:
        self.display_page_controls = True

    if self.count == 0 or self.offset > self.count:
        return []
    return list(queryset[self.offset:self.offset + self.limit])

2. 调用 get_limit 方法获取 limit

def get_limit(self, request):
    if self.limit_query_param:  # limit_query_param 为'limit'
        try:
            return _positive_int(
                request.query_params[self.limit_query_param],
                strict=True,
                cutoff=self.max_limit  # 最大limit
            )
        except (KeyError, ValueError):
            pass

    return self.default_limit  # drf中默认设置为None,可以在类中配置

3. 设置了limit_query_param时,self.limit 为调用_positive_int方法后的结果

def _positive_int(integer_string, strict=False, cutoff=None):
    """
    Cast a string to a strictly positive integer.
    """
    ret = int(integer_string)  # url传入的值,在url中:car/?limit=4.则ret=4
    if ret < 0 or (ret == 0 and strict):
        raise ValueError()
    if cutoff:
        return min(ret, cutoff)
    return ret

4. 调用 get_offset方法获取 offset

def get_offset(self, request):
    try:
        return _positive_int(
            request.query_params[self.offset_query_param],  # offset_query_param = 'offset'
        )
    except (KeyError, ValueError):
        return 0

原文地址:https://www.cnblogs.com/863652104kai/p/11523548.html

时间: 2024-10-01 23:29:13

drf - 偏移分页组件 LimitOffsetPagination的相关文章

DRF的分页组件,过滤组件

目录 一.DRF中的分页组件 1. 分页组件的使用 二.DRF的过滤组件 1. 搜索过滤组件的使用 2. 排序过滤组件的使用 3. 自定义过滤类 三.过滤组件之分类与区间 1. 分类与区间的使用 四.VUE前端播放器组件 一.DRF中的分页组件 DRF自带的分页组件帮我们写好了分页功能,包括各种小问题的优化,已经能满足实际开发的需求. 这里介绍了DRF的两种分页组件 基础分页组件 偏移分页组件 1. 分页组件的使用 使用方法:类似DRF的序列化的使用方式 1. 新建一个pagination.py

签发token、校验token、多方式登录签发token的实现、自定义认证反爬规则的认证类、admin使用自定义User表:新增用户密码密文、群查接口各种筛选组件数据准备、drf搜索过滤组件、drf排序过滤组件、drf基础分页组件

签发token 源码入口 # 前提:给一个局部禁用了所有 认证与权限 的视图类发送用户信息得到token,其实就是登录接口 # 1)rest_framework_jwt.views.ObtainJSONWebToken 的 父类 JSONWebTokenAPIView 的 post 方法 # 接收有username.password的post请求 # 2)post方法将请求得到的数据交给 rest_framework_jwt.serializer.JSONWebTokenSerializer 处

drf框架 token签发与校验、过滤/筛选/排序/分页组件

一.token 1.签发token 1)源码: # 前提:给一个局部禁用了所有 认证与权限 的视图类发送用户信息得到token,其实就是登录接口 # 1)rest_framework_jwt.views.ObtainJSONWebToken 的 父类 JSONWebTokenAPIView 的 post 方法 # 接受有username.password的post请求 # 2)post方法将请求数据交给 rest_framework_jwt.serializer.JSONWebTokenSeri

DRF框架(八)——drf-jwt手动签发与校验、过滤组件、筛选组件、排序组件、分页组件

自定义drf-jwt手动签发和校验 签发token源码入口 前提:给一个局部禁用了所有 认证与权限 的视图类发送用户信息得到token,其实就是登录接口,不然进不了登录页面 获取提交的username和password 1)rest_framework_jwt.views.ObtainJSONWebToken 的 父类 JSONWebTokenAPIView 的 post 方法 接受有username.password的post请求校验数据,并且签发token 2)post方法将请求数据交给 r

drf框架中分页组件

0922自我总结 drf框架中分页组件 普通分页(最常用) 自定制分页类 pagination.py from rest_framework.pagination import PageNumberPagination # 普通分页 class CarPageNumberPagination(PageNumberPagination): # 默认一页的条数 page_size = 3 # 用户可以自定义选择一页的条数,但最多显示5条 page_size_query_param = 'page_s

DRF ---- 过滤组件 分页组件 过滤组件插件使用

目录 DRF过滤组件 1 源码分析: 2 全局配置 过滤 类们 3 局部配置 过滤 类们 4 系统提供 过滤 类们 OrderingFilter(排序过滤) SearchFilter(查询过滤) 联合使用 DRF分页组件 1 全局配置 2 局部配置 3 PageNumberPagination基础分页 4 LimitOffsetPagination偏移分页 5 CursorPagination游标分页 加密分页(了解) 6.自定义过滤器 7 django-filter 过滤插件(重点) 安装 自

DRF 分页组件

Django Rest Framework 分页组件 DRF的分页 为什么要使用分页 其实这个不说大家都知道,大家写项目的时候也是一定会用的, 我们数据库有几千万条数据,这些数据需要展示,我们不可能直接从数据库把数据全部读取出来, 这样会给内存造成特别大的压力,有可能还会内存溢出,所以我们希望一点一点的取, 那展示的时候也是一样的,总是要进行分页显示,我们之前自己都写过分页. 那么大家想一个问题,在数据量特别大的时候,我们的分页会越往后读取速度越慢, 当有一千万条数据,我要看最后一页的内容的时候

DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)

url控制 第二种写法(只要继承了ViewSetMixin) url(r'^pub/$',views.Pub.as_view({'get':'list','post':'create'})), #获取所有记得路由后面加$结束符 #pub/?format=json url(r'^pub\.(?P<format>\w+)$',views.Pub.as_view({'get':'list','post':'create'})), #pub.json url(r'^pub/(?P<pk>\

DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分页组件 七 xxx 八 xxx 一 认证组件 1. 局部认证组件 我们知道,我们不管路由怎么写的,对应的视图类怎么写的,都会走到dispatch方法,进行分发, 在咱们看的APIView类中的dispatch方法的源码中,有个self.initial(request, *args, **kwargs),那么认证.权限.频率这三个默认组件都在这个方法里面了,如果我们自己没有做这三个组件的配置,那么会使用源码中默