15.1 分页

页模式

rest framework中提供了三种页模式

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination

全局配置

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 100
}

局部配置 

15.1.2 drf局部分页设置

视图中指明自定义的分页类

# HeroListCreateAPIView/?page=2&size=2  查询第2页,每页2条的英雄信息
class HeroListCreateAPIView(ListCreateAPIView):
    queryset = Hero.objects.all()  # 查询serializer_class = HeroModelSerializer  # 自己定义序列化器
    # 没有指明分页类,会按照全局分页
    pagination_class = Pagination  # 使用自定义的分页类

15.1.3 drf自定义分页类对象重写分页属性

自定义分页类,实现属性重写

# 只有某些视图需要分页, 可以自定义分页类
class Pagination(PageNumberPagination):
    page_size = 1  # 每页数量
    max_page_size = 3  # 每页最大的数量  以访特殊情况写不写都行
    page_size_query_param = 'size'  # 每页数量的参数名  供前端使用page_query_param = 'page'  # 页码参数名2

我们可以在视图类中进行这样的局部设置

class PublisherViewSet(ModelViewSet):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer
    pagination_class = PageNumberPagination      # 注意不是列表(只能有一个页模式

 DRF内置分页器

1、PageNumberPagination

页码数分页,第n页,每页显示m条数据,例如http://127.0.0.1:8000/api/article/?page=2&size=1

分页器

# 重写
class MyPageNumber(PageNumberPagination):
    page_size = 2                   # 每页显示多少条
    page_size_query_param = 'size'  # URL中每页显示条数参数
    page_query_param = 'page'       # URL中页码参数
    max_page_size = None            # 最大页码限制
 
# 如果我要的数据是第一页显示10条: http://127.0.0.1:8000/books/?size=10&page=1
# 如果我要的是第二页显示5条: http://127.0.0.1:8000/books/?size=5&page=2
# max_page_size = 8 :控制最大显示多少条如果我想第一页显示10000条,这种不合理,通过这个参数控制,最大显示8条

视图

class ArticleList(APIView):
    def get(self, request, *args, **kwargs):
        res = {"code": 0}
        article_list = models.Article.objects.all().order_by("id")
        # 分页
        page_obj = MyPageNumber()
        page_article = page_obj.paginate_queryset(queryset=article_list, request=request, view=self)
        ser_obj = ArticleSerializer(page_article, many=True)
        res["data"] = ser_obj.data
        return Response(res)

返回页码链接响应

class ArticleList(APIView):
    def get(self, request, *args, **kwargs):
        res = {"code": 0}
        article_list = models.Article.objects.all().order_by("id")
        # 分页
        page_obj = MyPageNumber()
        page_article = page_obj.paginate_queryset(queryset=article_list, request=request, view=self)
        ser_obj = ArticleSerializer(page_article, many=True)
        res["data"] = ser_obj.data
        return page_obj.get_paginated_response(res)

2、LimitOffsetPagination 

分页,在n位置,向后查看m条数据,例如http://127.0.0.1:8000/api/article/?offset=2&limit=2

分页器

# offset分页
class MyLimitOffset(LimitOffsetPagination):
    default_limit = 5             # 默认偏移条数 5
    limit_query_param = 'limit'   # 偏移条数
    offset_query_param = 'offset' # 从哪开始偏移
    max_limit = 999               # 偏移最大条数
 
-http://127.0.0.1:8000/books/ 结果是:从1到5
-http://127.0.0.1:8000/books/?limit=7 结果是:从1到7
-http://127.0.0.1:8000/books/?limit=2&offset=6 结果是:从7到8,两条
-http://127.0.0.1:8000/books/?offset=6 结果是:从7到11,5条

视图 

class ArticleList(APIView):
    def get(self, request, *args, **kwargs):
        res = {"code": 0}
        article_list = models.Article.objects.all().order_by("id")
        # 分页
        page_obj = MyLimitOffset()
        page_article = page_obj.paginate_queryset(queryset=article_list, request=request, view=self)
        ser_obj = ArticleSerializer(page_article, many=True)
        res["data"] = ser_obj.data
        return page_obj.get_paginated_response(res)

3、CursorPagination

加密分页,把上一页和下一页的id记住

分页器 

# 加密分页
class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'
    page_size = 1         # 每页显示的条数
    ordering = '-id'      # 按谁排序

视图

class ArticleList(APIView):
    def get(self, request, *args, **kwargs):
        res = {"code": 0}
        article_list = models.Article.objects.all().order_by("id")
        # 分页
        page_obj = MyCursorPagination()
        page_article = page_obj.paginate_queryset(queryset=article_list, request=request, view=self)
        ser_obj = ArticleSerializer(page_article, many=True)
        res["data"] = ser_obj.data
        # return Response(res)
        return page_obj.get_paginated_response(res)

15.2 过滤

15.2.1 djangofilter精准过滤

django-filter包含一个DjangoFilterBackend类,该类支持针对REST框架高度可自定义字段筛选

使用DjangoFilterBackend,请先安装django-filter

pip install django-filter

添加'django_filters'到DjangoINSTALLED_APPS

INSTALLED_APPS = [
    ...
    'django_filters',
    ...
]

过滤器后端添加全局设置中:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}

 或将过滤器后端添加到单个ViewViewSet

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.generics import ListAPIView

class GoodsListAPIView(ListAPIView):
    ...
    filter_backends = (DjangoFilterBackend,)

如果只需要简单基于模型类字段等式过滤,则可以filterset_fields在视图或视图集上设置一个属性列出过滤的字段集。

class GoodsListAPIView(ListAPIView):
    queryset = GoodsModel.objects.all()
    serializer_class = GoodsModelSerializer

    # filter_backends = (DjangoFilterBackend, )  # 如果全局设置过,局部需要设置
    filter_fields = ('price', 'name')

FilterSet自动给定的字段创建一个类,并允许您发出如下请求

http://127.0.0.1:8000/api/goods/?price=5&name=西瓜

15.2.2 djangofilter模糊过滤

定义过滤器,实现高级过滤

class GoodsFilter(django_filters.rest_framework.FilterSet):
    """商品的过滤类"""
    min_price = django_filters.NumberFilter(field_name="price",lookup_expr="gte")
    # field_name 表示要过滤字段;lookup_expr 表示 过滤时要进行的操作,gte 表示 大于等于
    max_price = django_filters.NumberFilter(field_name="price", lookup_expr="lte")  # lte 小于等于

    name = django_filters.CharFilter(field_name="name", lookup_expr="icontains")  # icontains 表示 包含忽略大小写)

    class Meta:
        model = GoodsModel  # 关联的表
        fields = ["min_price", "max_price", "name"]  # 过滤的字段

class GoodsListAPIView(ListAPIView):
    queryset = GoodsModel.objects.all()
    serializer_class = GoodsModelSerializer        
    filterset_class = GoodsFilter  # 指明过滤器类

FilterSet自动给定的字段创建一个类,并允许您发出如下请求

http://127.0.0.1:8000/api/goods/?max_price=50&name=瓜

15.2.3 rest_framework的SearchFilter

搜索引擎依赖于 rest_framework, 不需要安装额外插件

将过滤器后端添加到全局设置中:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter']
}

或将过滤器后端添加到单个ViewViewSet

from rest_framework.filters import SearchFilter
from rest_framework.generics import ListAPIView

class GoodsListAPIView(ListAPIView):
    ...
    filter_backends = [SearchFilter]
from rest_framework.filters import SearchFilter
from rest_framework.generics import ListAPIView

class GoodsListAPIView(ListAPIView):
    ...
    search_fields = ['name']

这将允许客户端通过执行以下查询来过滤列表中的项目

http://127.0.0.1:8000/api/goods/?search=西瓜汁

您还可以使用查找API双下划线表示法在ForeignKey或ManyToManyField上执行相关查找

search_fields = ['name', 'cate__name']

默认情况下,搜索将使用不区分大小写部分匹配。搜索参数可以包含多个搜索词,应将其用空格逗号分隔。如果使用多个搜索词,则仅当所有提供的词都匹配时,对象才会在列表中返回。

可以通过在字符前面添加各种字符限制搜索行为search_fields

模糊搜索和排序 代码实现

 pip install django-filter

# settings配置 注册一下

INSTALLED_APPS = [
    'django_filters',
]
# 序列化器

class ShopSer(serializers.ModelSerializer):
    # 如有外键,当声明 可供搜索使用
    # kind = serializers.StringRelatedField(read_only=True)
    class Meta:
        model = Shop
        fields = '__all__'
#视图

from rest_framework.generics import ListAPIView
from rest_framework.filters import OrderingFilter, SearchFilter


class ShopFunction(ListAPIView):
    queryset = Shop.objects.all()
    serializer_class = ShopSer
    filter_backends = [OrderingFilter, SearchFilter]
    search_fields = ['id', 'name']  # 如有外键kind_id,即为'kind__id'
    ordering_fields = ['id']
# 路由路由shop/

from django.urls import path

from shop import views

urlpatterns = [
    path('shopfunction/', views.ShopFunction.as_view()),
]
# 前端请求

# http://127.0.0.1:8000/shop/shopfunction/?search=鸡排

let url = 'shop/shopfunction/?search=' + this.name
get(url)



# http://127.0.0.1:8000/shop/shopfunction/?ordering=-id

let url = 'shop/shopfunction/?ordering=-id'
get(url)

原文地址:https://blog.csdn.net/Ben_boba/article/details/126588621

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_40646.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注