基于DRF的实现排序、过滤、分页

【 一 】排序

  1. 获取所有接口–》才有排序

  2. 必须继承GenericAPIView

  3. 视图类中配置

    • #     filter_backends = [OrderingFilter]
      
    • #	ordering_fields=['price','name']
      
  4. http://127.0.0.1:8008/seven/books/?ordering=price,-name

  • 相关的导入包

from rest_framework.authentication import BaseAuthentication # 认证
from rest_framework.permissions import BasePermission   # 权限
from rest_framework.throttling import SimpleRateThrottle # 频率
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import JSONParser

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin
from rest_framework.viewsets import ViewSetMixin, GenericViewSet
from rest_framework.generics import ListAPIView
from .models import Book
from .serializer import BookSerializer
from rest_framework.response import Response
from rest_framework.filters import SearchFilter,OrderingFilter

方法一:

  • http://127.0.0.1:8200/two/books1/?price
class BOOKViewss(GenericViewSet, ListModelMixin,CreateModelMixin):
    # 配置认证类为LoginAuth
    # authentication_classes = [LoginAuth]
    # throttle_classes = [IPBasedRateThrottle]
    # permission_classes = []

    queryset = Book2.objects.all()
    serializer_class = BookSerializer

    def list(self, request, *args, **kwargs):
        query=request.query_params.get('ordering')
        qs = self.get_queryset()
        if query:
            qs=qs.order_by(query)
        ser=self.get_serializer(instance=qs,many=True)
        return Response(ser.data)

image-20240418132451046

方法二:

# 必须是查询所有接口--》restful规范中:地址栏中带过滤条件
# 正序
http://127.0.0.1:8200/two/books1/?ordering=price

# 倒序
http://127.0.0.1:8200/two/books1/?ordering=-price        
  
# 其他的自我实现
http://127.0.0.1:8200/two/books1/?ordering=-price,name
# 必须导入的函数(就是过滤)
from rest_framework.filters import OrderingFilter

filter_backends = [OrderingFilter]
ordering_fields = ['price']

from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, ListModelMixin, \
    UpdateModelMixin
from rest_framework.viewsets import GenericViewSet
from .models import Book2

from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import ViewSet
from .permissions import UserPermission
from .authaction import LoginAuth
from .throttling import WecelomeThrottling
from rest_framework.filters import OrderingFilter
class BOOKViewss(GenericViewSet, ListModelMixin):
    # 配置认证类为LoginAuth
    authentication_classes = [LoginAuth]
    permission_classes = []

    queryset = Book2.objects.all()
    serializer_class = BookSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ['price']
    # ordering_fields = ['price','name']

image-20240417215019982

image-20240417215058151

【 二 】过滤

内置过滤

# 排序 过滤
from rest_framework.filters import OrderingFilter,SearchFilter

# 也可以多个字段模糊匹配
    search_fields = ['name', 'publish']
    
    
    # 排序跟过滤不冲突
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    #  SearchFilter内置的,固定用法,模糊匹配
    #  就有过滤功能了,指定按哪个字段过滤
    filter_backends = [SearchFilter]
    # search_fields = ['name']  # 可以按名字模糊匹配
    search_fields = ['name','price']  # 可以按名字模糊匹配或价格
    
    
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, ListModelMixin, \
    UpdateModelMixin
from rest_framework.viewsets import GenericViewSet
from .models import Book2

from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import ViewSet
from .permissions import UserPermission
from .authaction import LoginAuth
from .throttling import WecelomeThrottling
# 排序 过滤
from rest_framework.filters import OrderingFilter,SearchFilter
from rest_framework.decorators import permission_classes
class BOOKViewss(GenericViewSet, ListModelMixin):
    # 配置认证类为LoginAuth
    authentication_classes = [LoginAuth]
    permission_classes = []

    queryset = Book2.objects.all()
    serializer_class = BookSerializer
    filter_backends = [OrderingFilter,SearchFilter]

    ordering_fields = ['price','name']

    # 也可以多个字段模糊匹配
    search_fields = ['name', 'publish']

第三方过滤

	1 安装第三方模块:pip3 install django-filter
    # 安装最好在Pycharm中进行安装
    2 视图类中配置
    class BookListView(GenericViewSet, ListModelMixin):
        ### 2 第三方过滤类
        filter_backends = [DjangoFilterBackend]
        filterset_fields = ['price', 'name']

image-20240417233357075

自定义过滤类

​ 想怎么查,就怎么查

  1. 写个类,继承BaseFilterBackend

  2. 重写filter_queryset,在里面对qs对象进行过滤

  3. 把过滤结果返回回来

  4. 视图类中配置

    • # filter_backends = [CommonFilter]	
      

  • -多个排序或过滤是可以同时使用的:

  • filter_backends = [CommonFilter]
    
  • -大原则,把一次性过滤掉很多的往前放

  • -猜内部实现:for循环一个个过滤类,执行过滤类的filter_queryset方法

创建一个filters.py文件重写filter_queryset函数

# 第一步,写一个类,继承基类BaseFilterBackend,重写某个方法filter_queryset,返回的数据就是过滤后的qs对象
# 配置一下,在视图类中配置
# 一般就局部配置就够了
filter_backends = [FilterByName]
### 过滤类
from rest_framework.filters import BaseFilterBackend
class FilterByName(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        #http://127.0.0.1:8000/book/?name=红楼梦
        query=request.query_params.get('name')
        if query:
            return queryset.filter(name__contains= query )
        else:
            return queryset

        return queryset
  • views.py

from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, ListModelMixin, \
    UpdateModelMixin
from rest_framework.viewsets import GenericViewSet
from .models import Book2
# 自己定义的过滤类
from two.filters import PriceRangeFilter,FilterByName
class BOOKViewss(GenericViewSet, ListModelMixin,CreateModelMixin):

    queryset = Book2.objects.all()
    serializer_class = BookSerializer
    filter_backends = [FilterByName]

image-20240418133530554

【 三 】分页

这就是大致的方法

# 三种分页方式,需要重写类属性(另建一个pagination.py文件,写入重写类)
from rest_framework.pagination import CursorPagination, LimitOffsetPagination, PageNumberPagination


# 1基本分页
class CommonPageNumberPagination(PageNumberPagination):
    # 定制几个类属性
    page_size = 2  # 每页显示2条
    page_query_param = 'page'  # http://127.0.0.1:8200/two/books1/?page=2
    page_size_query_param = 'size'  # http://127.0.0.1:8200/two/books1/?page=2&size=3
    max_page_size = 10  # 每页最多显示10条
    # http://127.0.0.1:8200/two/books1/?page=2 查询第二页,每页显示2条
    #http://127.0.0.1:8200/two/books1/?page=1&size=5查询第一页,每页显示5


# 2 limit  offset分页方式  偏移分页
class CommonLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 2  # 每页显示两条
    # http://127.0.0.1:8200/two/books1/?limit=4  一页显示四条
    limit_query_param = 'limit'  # 控制每页显示多少条
    # http://127.0.0.1:8200/two/books1/?offset=3  从第3条开始,取两条
    # v?offset=3&limit=1  从第3条开始,取1条
    offset_query_param = 'offset'  # 偏移量
    max_limit = 10  # 最大每页取10条


# 游标分页-->必须要排序--》只能取上一页和下一页,不能直接跳转到某一页 效率高, 大数据量 app端使用
class CommonCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 查询条件 http://127.0.0.1:8200/two/books1/?cursor=asfasf
    page_size = 2
    ordering = 'id'




#### 在视图类中使用
#(先将重写类导入)
from .pagination import MyPageNumberPagination as PageNumberPagination
from .pagination import MyLimitOffsetPagination as LimitOffsetPagination
from .pagination import MyCursorPagination as CursorPagination

class BookView(ViewSetMixin, ListAPIView):
    # 带分页功能
    pagination_class = CursorPagination # 配置成你重写的类

 # 全局使用
    'DEFAULT_PAGINATION_CLASS': None,

image-20240418134926994

一个结合小示例

让我们实现这个方法

  1. 图书查询所有接口
  2. ​ -图书名 和 price范围过滤
  3. ​ price_gt=10&price_lt=100

​ 首先,你需要创建一个自定义的过滤器类。在你的应用中创建一个名为 filters.py 的文件,并在其中定义你的过滤器类,例如:

from rest_framework import filters

class PriceRangeFilter(filters.BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        price_gt = request.query_params.get('price_gt')
        price_lt = request.query_params.get('price_lt')

        if price_gt is not None:
            queryset = queryset.filter(price__gt=price_gt)
        if price_lt is not None:
            queryset = queryset.filter(price__lt=price_lt)

        return queryset

再将PriceRangeFilter类导入到视图层

image-20240417223115702

from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, ListModelMixin, \
    UpdateModelMixin
from rest_framework.viewsets import GenericViewSet
from .models import Book2

from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import ViewSet
from .permissions import UserPermission
from .authaction import LoginAuth
from .throttling import WecelomeThrottling
# 排序 过滤
from rest_framework.filters import OrderingFilter,SearchFilter
from rest_framework.decorators import permission_classes
from .page import CommonCursorPagination,CommonPageNumberPagination,CommonLimitOffsetPagination
# 自己定义的过滤类
from two.filters import PriceRangeFilter
class BOOKViewss(GenericViewSet, ListModelMixin,CreateModelMixin):
    # 配置认证类为LoginAuth
    authentication_classes = [LoginAuth]
    permission_classes = []

    queryset = Book2.objects.all()
    serializer_class = BookSerializer
    # 排序 、 过滤 、 过滤类
    filter_backends = [OrderingFilter,SearchFilter,PriceRangeFilter]
    # pagination_class = CommonPageNumberPagination # 分页方式只能选择一种
    # pagination_class = CommonLimitOffsetPagination # 分页方式只能选择一种
    # pagination_class = CommonCursorPagination  # 分页方式只能选择一种

    ordering_fields = ['price','name']

    # 也可以多个字段模糊匹配
    search_fields = ['name', 'publish']

image-20240417222912055

ot None:
queryset = queryset.filter(price__lt=price_lt)

    return queryset

再将`PriceRangeFilter`类导入到视图层

[外链图片转存中...(img-jcx74dMr-1715388019077)]

```python
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, ListModelMixin, \
    UpdateModelMixin
from rest_framework.viewsets import GenericViewSet
from .models import Book2

from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import ViewSet
from .permissions import UserPermission
from .authaction import LoginAuth
from .throttling import WecelomeThrottling
# 排序 过滤
from rest_framework.filters import OrderingFilter,SearchFilter
from rest_framework.decorators import permission_classes
from .page import CommonCursorPagination,CommonPageNumberPagination,CommonLimitOffsetPagination
# 自己定义的过滤类
from two.filters import PriceRangeFilter
class BOOKViewss(GenericViewSet, ListModelMixin,CreateModelMixin):
    # 配置认证类为LoginAuth
    authentication_classes = [LoginAuth]
    permission_classes = []

    queryset = Book2.objects.all()
    serializer_class = BookSerializer
    # 排序 、 过滤 、 过滤类
    filter_backends = [OrderingFilter,SearchFilter,PriceRangeFilter]
    # pagination_class = CommonPageNumberPagination # 分页方式只能选择一种
    # pagination_class = CommonLimitOffsetPagination # 分页方式只能选择一种
    # pagination_class = CommonCursorPagination  # 分页方式只能选择一种

    ordering_fields = ['price','name']

    # 也可以多个字段模糊匹配
    search_fields = ['name', 'publish']

[外链图片转存中…(img-WhwmhBPu-1715388019077)]

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DRF实现多层级数据的方法主要有两种: 1. 使用 Serializer 嵌套来实现多层级数据 在 Serializer 中可以使用嵌套的方式来表示多层级数据结构,例如: ```python class SubItemSerializer(serializers.ModelSerializer): class Meta: model = SubItem fields = '__all__' class ItemSerializer(serializers.ModelSerializer): sub_items = SubItemSerializer(many=True) class Meta: model = Item fields = '__all__' ``` 在上面的例子中,SubItemSerializer 表示 SubItem 模型的序列化器,ItemSerializer 表示 Item 模型的序列化器,其中 Item 中包含多个 SubItem。通过将 SubItemSerializer 嵌套在 ItemSerializer 中,就能够实现多层级数据的序列化与反序列化。 2. 使用 DRF 的 ModelViewSet 来实现多层级数据的 API DRF 提供了 ModelViewSet 来快速实现基于模型的 API,其中包含了常用的增删改查操作。在 ModelViewSet 中可以通过重写 queryset 和 serializer_class 来实现多层级数据的 API,例如: ```python class ItemViewSet(viewsets.ModelViewSet): queryset = Item.objects.all() serializer_class = ItemSerializer def get_serializer_class(self): if self.action == 'list': return ItemListSerializer return super().get_serializer_class() ``` 在上面的例子中,ItemViewSet 是一个基于 Item 模型的 API,其中 queryset 表示查询的数据集,serializer_class 表示序列化的类。如果需要实现多层级数据的 API,可以在 ItemSerializer 中嵌套 SubItemSerializer,同时根据需要重写 get_serializer_class 方法来选择不同的序列化器。例如,在 list 操作中,可以选择 ItemListSerializer 来表示列表中的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值