drf之restful规范中的过滤、排序和分页
一、过滤
restful规范中
-请求地址中带过滤条件
带过滤的接口只有:查询所有
内置过滤类
from rest_framework.filters import SearchFilter
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [SearchFilter]
# 支持这种搜索
# # http://127.0.0.1:8000/api/v1/books/?search=红
# search_fields = ['name']
#http://127.0.0.1:8000/api/v1/books/?search=11 只要name或price中带11都能搜出来
search_fields = ['name','price']
第三方过滤类
### 2.1 第三方过滤类
# pip3 install django-filter
from django_filters.rest_framework import DjangoFilterBackend
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [DjangoFilterBackend]
# http://127.0.0.1:8000/api/v1/books/?name=红楼梦&price=45
# 按名字和价格精准匹配
filterset_fields = ['name', 'price']
记得注册
自定义过滤类 价格再100----200之间的图书
from .filter import MyFilter
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [MyFilter]
# 必须配合一个过滤类
新建一个filter文件夹,自己新写一个过滤类
from rest_framework import filters
from django.db.models import Q
class MyFilter(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
# 返回的数据,就是过滤后的数据
# http://127.0.0.1:8000/api/v1/books/?price=44&name=红楼梦 按名字或价格
price = request.query_params.get('price')
name = request.query_params.get('name')
queryset = queryset.filter(Q(name=name) | Q(price=price))
return queryset
# 过滤和排序可以一起使用
二、排序
restful规范中
-请求地址中带过滤条件
排序功能的接口:查询所有
from rest_framework.filters import OrderingFilter
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [OrderingFilter] # 排序类
# 配合一个类属性,按哪些字段可以排序
# http://127.0.0.1:8000/api/v1/books/?ordering=-price,-id
# 先按价格倒序排,价格一样,再按id倒叙排
ordering_fields = ['price','id']
三、分页
查询所有接口,过滤和排序了,但是实际上,这个接口,都需要有分页功能
-分页的展现形式
web:下一页点解
app,小程序:下滑下一页
-接口都一样,要支持分页
drf提供给咱们,三种分页方式
基本分页
偏移分页
游标分页
from .page import MyPageNumberPagination,MyLimitOffsetPagination,MyCursorPagination
# 这种方式用的多
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
# http://127.0.0.1:8000/api/v1/books/?page=2&page_size=3
# pagination_class = MyPageNumberPagination # 只能按一种方式分页,不要放到列表中了
# http://127.0.0.1:8000/api/v1/books/?limit=4&offset=3 # 从第三条数据开始,取4条
# pagination_class = MyLimitOffsetPagination # 只能按一种方式分页,不要放到列表中了
pagination_class = MyCursorPagination # 只能按一种方式分页,不要放到列表中了
新建一个page.py文件
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
## 基本分页
class MyPageNumberPagination(PageNumberPagination):
# 重写几个类属性 :4个
page_size = 2 # 每页显示的条数
page_query_param = 'page' # page=4 表示第4页
page_size_query_param = 'page_size' # page=4&page_size=5 表示查询第4页,每页显示5条
max_page_size = 5 # 每页最大显示多少条
## 偏移分页
class MyLimitOffsetPagination(LimitOffsetPagination):
# 重写几个类属性 :4个
default_limit = 2 # 每页显示多少条
limit_query_param = 'limit' # limit=3 这一页取3条
offset_query_param = 'offset' # 偏移量是多少 offset=3&limit=2 从第3条开始,拿2条
max_limit = 5 # 最多取5条
## 游标分页,只能上一页和下一页,不能直接跳到某一页,但是这个的速度快---》app上用它多
class MyCursorPagination(CursorPagination):
# 重写几个类属性 :3个
cursor_query_param = 'cursor' # 查询参数,其实用不到
page_size = 2 # 每页显示多少条
ordering = 'id' # 必须是要分页的数据表中的字段,一般按id来
作业
继承APIView,实现上面1,2
过滤和排序
from rest_framework.views import APIView
from .models import Book
from .serializer import BookSerialzer
from rest_framework.response import Response
class BookView(APIView):
def get(self,request):
ordering = request.query_params.get('ordering')
name = request.query_params.get('name')
book_list = Book.objects.all()
if ordering:
book_list = book_list.order_by(ordering)
if name:
book_list = book_list.filter(name__contains=name)
ser = BookSerialzer(instance=book_list,many=True)
return Response(ser.data)
带分页
# 带分页
from .page import MyPageNumberPagination
from rest_framework.mixins import ListModelMixin
from rest_framework.generics import GenericAPIView
class BookView(APIView):
def get(self, request):
ordering = request.query_params.get('ordering')
name = request.query_params.get('name')
book_list = Book.objects.all()
if ordering:
book_list = book_list.order_by(ordering)
if name:
book_list = book_list.filter(name__contains=name)
# 加入分页
# page=MyPageNumberPagination().paginate_queryset(book_list, request,self)
pagination = MyPageNumberPagination()
page = pagination.paginate_queryset(book_list, request, self)
ser = BookSerialzier(instance=page, many=True)
return Response({'code': 100, 'msg': '成功',
'count': pagination.page.paginator.count,
'next': pagination.get_next_link(),
'previous': pagination.get_previous_link(),
'results': ser.data})
''' 根据源码写自己的分页
# 配置的分页类的对象调用了paginate_queryset(queryset, self.request, view=self)
page = self.paginate_queryset(queryset) # 是paginate_queryset的GenericAPIView
if page is not None:
# 把page进行了序列化
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data) # GenericAPIView--》self.paginator.get_paginated_response(data)
return Response(OrderedDict([
('count', self.page.paginator.count),
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('results', data)
]))
'''