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

 

 

posted @ 2020-07-17 21:53  10132714  阅读(159)  评论(0编辑  收藏  举报