rest-framework - 分页,视图,路由和过滤
1. 分页
当数据量过大,如何修改查询规则:
显示当前页的时候记录当前的最大id(和最小id,上一页的时候用的),假设为n,下一页的时候查询条件是id>n,这样,前n条就不用扫描了。(这里只显示上一页和下一页,没有具体页码)
但是有一个缺点就是当用户修改url直接改成较大的数的时候还是会出现相同的情况。这是时我们把页码进行加密,这样用户就不能通过修改url来获取我们的数据了。
分页有三个类
1. PageNumberPagination
class StandardResultsSetPagination(PageNumberPagination): # 继承PageNumberPagination,就可以指定这些参数,不然需要在settings中加入配置 # 默认每页显示的数据条数 page_size = 1 # 获取URL参数中设置的每页显示数据条数 page_size_query_param = 'page_size' # 获取URL参数中传入的页码key page_query_param = 'page' # 最大支持的每页显示的数据条数 max_page_size = 1 class UserSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__" class UserViewSet(APIView): def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().order_by('-id') # 实例化分页对象,获取数据库中的分页数据 paginator = StandardResultsSetPagination() page_user_list = paginator.paginate_queryset(queryset=user_list, request=self.request, view=self) # 序列化对象 serializer = UserSerializer(page_user_list, many=True) # 生成分页和数据 response = paginator.get_paginated_response(serializer.data) # 这种方式是作为返回对象,响应体中会有上一页下一页的url return response
2. LimitOffsetPagination(使用方法同一,配置参数不同)
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination class StandardResultsSetPagination(LimitOffsetPagination): # 默认每页显示的数据条数 default_limit = 10 # URL中传入的显示数据条数的参数 limit_query_param = 'limit' # 搜寻多少个数据 # URL中传入的数据位置的参数 offset_query_param = 'offset' # 从哪一条记录开始往后搜 # 最大每页显得条数 max_limit = None class UserSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__" class UserViewSet(APIView): def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().order_by('-id') # 实例化分页对象,获取数据库中的分页数据 paginator = StandardResultsSetPagination() page_user_list = paginator.paginate_queryset(user_list, self.request, view=self) # 序列化对象 serializer = UserSerializer(page_user_list, many=True) # 生成分页和数据 response = paginator.get_paginated_response(serializer.data) return response
3. CursorPagination(使用方法同一,配置参数不同)(只显示上一页,下一页,没有其他页码)
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination class StandardResultsSetPagination(CursorPagination): # URL传入的游标参数 cursor_query_param = 'cursor' # 默认每页显示的数据条数 page_size = 2 # URL传入的每页显示条数的参数 page_size_query_param = 'page_size' # 每页显示数据最大条数 max_page_size = 1000 # 根据ID从大到小排列 ordering = "id" class UserSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__" class UserViewSet(APIView): def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().order_by('-id') # 实例化分页对象,获取数据库中的分页数据 paginator = StandardResultsSetPagination() page_user_list = paginator.paginate_queryset(user_list, self.request, view=self) # 序列化对象 serializer = UserSerializer(page_user_list, many=True) # 生成分页和数据 response = paginator.get_paginated_response(serializer.data) return response
2. 路由与渲染器
1. 路由
如果前端需要获得json数据,可以通过访问url
/api/v1/user/?format=json(普通方式)
或者/api/v1/user.json(rest-framework提供的额外方式)
实现方法:
记不太清了。里面有个router。然后注册视图:router.register('user', views.UserInfoView) # view.UserInfoView是需要做路由的视图,user会在url中使用,/api/v1/user
2. 渲染器(即返会的数据将会以什么样的格式显示)
class TestView(APIView):
renderer_classes = [JSONRenderer, BrowsableAPIRenderer] # 视图中这样配置即可,它会自动识别
def get(self, request, *args, **kwargs):
user_list = models.UserInfo.objects.all()
ser = TestSerializer(instance=user_list, many=True)
return Response(ser.data)
3. 视图
GenericAPIView继承了APIView,里面封装了queryset,pagination,serializer等方法 ------- 单纯的用这个方法没有意义
GenericViewSet继承了ViewSetMixin和GenericAPIView,此时路由里面多了一个对应关系.as_view({'get': 'list'})。当请求方式为get时,执行该类的list方法,没有就去父类里面找
ModelViewSet继承了mixins.ListModelMixin, mixins.CreateModelMixin, ...,GenericViewSet等六个类 ---- 功能最全
仅举例ModelViewSet的使用
url.py
urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list', 'post': 'create'})), # 需要指定id的情况,这里的retrieve是用来获取单条数据 url(r'^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$', views.View1View.as_view({'get': 'retrieve', 'delete': 'destroy'})), ]
views.py
from rest_framework.viewsets import ModelViewSet class View1View(ModelViewSet): queryset = models.Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination