18 过滤排序分页异常处理

1.过滤

# 只针对于查询所有接口
# 127.0.0.1:8000/four/students/?sex=1

-内置过滤类SearchFilter,配置search_fields,指定过滤的字段,可以模糊匹配,?search=搜索条件
-自定义过滤类:写一个类,继承BaseFilterBackend,重写filter_queryset方法,方法返回qs对象,就是过滤后的对象,配置在视图类中即可
-django-filter,导入DjangoFilterBackend,配置在视图类上,配置filter_fields=['name','publish'],指定过滤字段,不能模糊匹配,?name=搜索条件

#models.py
from django.db import models

class Book(models.Model):
    name=models.CharField(max_length=32)
    price=models.IntegerField()
    publish=models.CharField(max_length=32)

#serializers.py
from rest_framework import serializers
from app01.models import Book
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model=Book
        fields="__all__"

#views.py
from django.shortcuts import render
from rest_framework.generics import GenericAPIView,ListAPIView
from rest_framework.mixins import ListModelMixin
from rest_framework.viewsets import ViewSetMixin,GenericViewSet
from app01.models import Book
from app01.serializer import BookSerializer
from rest_framework.response import Response
from rest_framework.filters import SearchFilter

#class BookView(ViewSetMixin,GenericAPIView,ListModelMixin):  #BookView三种写法
#class BookView(GenericViewSet,ListModelMixin):
class BookView(ViewSetMixin,ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 方式一:笨办法
    def list(self, request, *args, **kwargs):
        query=request.GET.get('name')
        qs=self.get_queryset().filter(name=query)
        ser=self.get_serializer(instance=qs,many=True)
        return Response(ser.data)
# 方式二:使用内置的过滤类(可以自己写,使用第三方)
    filter_backends=[SearchFilter,]   ## 过滤类:可以自己写,也可以用内置,使用第三方(filter_backends在ListAPIView的GenericAPIView中找

# SearchFilter类中通过反射获取的字段
search_fields=['name','publish'] # 按那个字段过滤,可以模糊匹配

# http://127.0.0.1:8000/book/?search=条件 并且支持模糊匹配

#urls.py
from django.contrib import admin
from django.urls import path
from app01.views import BookView
from rest_framework.routers import SimpleRouter
router=SimpleRouter()
router.register('book',BookView,'book')
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += router.urls



#settings.py需要注册'rest_framework',

 

 

 2.排序

内置排序类OrderingFilter,配置ordering_fields,指定排序的字段,可以实现排序,?ordering=-price

# class BookView(ViewSetMixin, ListAPIView):
#     queryset = Book.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)
#
#     ### 方式二:
#     filter_backends = [OrderingFilter]  # 内置的排序类
#     ordering_fields=['price']
#     # http://127.0.0.1:8000/book/?ordering=price  #升序
#     # http://127.0.0.1:8000/book/?ordering=-price #降序

 

 3.过滤排序连用(尽量把过滤写在前面)

### 排序过滤连用
# class BookView(ViewSetMixin, ListAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#
#     ### 方式:
#     filter_backends = [SearchFilter,OrderingFilter]  # 放在第一位的,最好能优先过滤掉很多数据
#     ordering_fields=['price']
#     search_fields = ['publish']
#    http://127.0.0.1:8000/book/?search=出版社&ordering=price

 

 

4.自定义过滤类(http://127.0.0.1:8000/book/?name=红,之前需要写成search=红,现在可以用自定义的name)

# 第一步,写一个类,继承基类BaseFilterBackend,重写某个方法filter_queryset,返回的数据就是过滤后的qs对象
# 配置一下,在视图类中配置
filter_backends = [FilterByName]

### 过滤类filters.py
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 .filters import FilterByName
# class BookView(ViewSetMixin, ListAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
#     filter_backends = [FilterByName]

5.django-filter的简单使用

## 使用第三方:django-filter,需要安装 pip3 install django-filter
# 是一个app,在项目中注册
# 导入django-filter提供的过滤类

 

 

#views.py

from django_filters.rest_framework import DjangoFilterBackend class BookView(ViewSetMixin, ListAPIView): queryset = Book.objects.all() serializer_class = BookSerializer filter_backends = [DjangoFilterBackend,] filter_fields=['name','publish'] # 不支持模糊匹配,只支持精准匹配,多个搜索条件是and,如果要用or,需要使用多表查询的Q查询


#settings.py
注册'django_filters',

 

 

 

6.分页的使用

PageNumberPagination:用的多,传统的分页 page=第几页&size=每页多少条
LimitOffsetPagination:从第几条开始offset=第几条,取几条limit=取几条
CursorPagination:只能选择看上一页或下一页,效率高

重写某个分页类,修改某几个类属性后,把分页类,配置在视图类上:pagination_class=分页类

# 三种分页方式,需要重写类属性
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

class MyPageNumberPagination(PageNumberPagination):
    page_size = 2  # 每页显示的条数
    page_query_param = 'p'  #http://127.0.0.1:8000/book/?page=3
    page_size_query_param = 's'  # 每页显示多少条
    max_page_size = 3    # 每页最大显示3条


class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 1  # 每页显示的条数
    limit_query_param = 'limit'  # 取几条
    offset_query_param = 'offset' # 标杆,从第几个位置开始取   默认情况,每页显示一条
    max_limit = 5  # 最大每页显示多少条



# 分页速度快,有缺陷,只能上一页和下一页,不能直接跳到某一页,针对于数据量大,可以使用该分页方式
class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 不用动,没有用
    page_size = 3  # 每页显示多少条
    ordering = 'id' # 游标分页的原理,是先排序,然后使用游标标志位置,只能往前,往后,所以只能上一页和下一页
#### 在视图类中使用views.py
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
from .pagination import MyPageNumberPagination as PageNumberPagination
from .pagination import MyLimitOffsetPagination as LimitOffsetPagination
from .pagination import MyCursorPagination as CursorPagination
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
serializer_class = BookSerializer
# 带分页功能
    #pagination_class =PageNumberPagination
    #pagination_class =LimitOffsetPagination
    pagination_class = CursorPagination # 配置成你重写的类,局部配置
# 全局使用
#settings.py
REST_FRAMEWORK={'DEFAULT_PAGINATION_CLASS': None,}

 

 基于APIview实现分页:

 

 

 

posted @ 2022-02-07 19:00  甜甜de微笑  阅读(94)  评论(0编辑  收藏  举报