Django Rest Framework全局分页参数不适用于ModelViewSet [英] Django rest framework global pagination parameters not working for ModelViewSet

查看:183
本文介绍了Django Rest Framework全局分页参数不适用于ModelViewSet的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

DRF文档指出:


只有在使用通用视图或视图集时,才会自动执行分页。


但是我使用的是 ModelViewSet ,该继承自 ViewSet ,所以我告诉自己很酷,我要做的就是将其添加到我的 settings.py 中:

 'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE':12,#适用于12列网格CSS框架

但是,这没用。

如果我发送GET请求获取27个项目它返回所有它们(在可浏览的API和json中)。




  • 我是否认为我应该只返回12?

  • Sub-问题: PAGE_SIZE是每页返回的顶级对象的数量,对吗?我看到了一些 PAGINATE_BY 的示例,但它的
    来源,所以我认为它已被弃用?



我正在使用DRF 3.6.3,django 1.11.2。



编辑:我的设置:

  REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES':((
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_RENDERER_CLASSES':((
'rest_framework.renderers.JSONRenderer ',
'rest_framework.renderers.BrowsableAPIRenderer',
),
'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE':12,
}

我还向中添加了 pagination_class = PageNumberPagination



这是外壳程序的验证,即Pagination类确实知道应该提供的页面大小:

 >>从rest_framework.pagination导入PageNumberPagination 
>> p = PageNumberPagination()
>> p.max_page_size
>> print(p.page_size)
12


解决方案

的确,尽管从 GenericViewSet 和<$ c $继承,但默认情况下分页在 ModelViewSet 上不起作用c> ListMixin 。您需要手动添加它:



我组成了问与答样式示例,它解决了该问题,并在 ModelViewSet

我会总结一下:


  1. 创建一个自定义mixin以使用 pagination_class

      class MyPaginationMixin(object ):
    @property
    def paginator(self):

    与视图关联的分页器实例,或`None`。

    如果没有hasattr(self,'_paginator'):
    如果self.pagination_class为None:
    self._paginator = None
    else:
    self._paginator = self。 pagination_class()
    返回self._paginator

    def paginate_queryset(self,queryset):

    返回单页结果,如果分页
    被禁用,则返回无。

    如果self.paginator为None:
    返回None
    返回self.paginator.paginate_queryset(
    queryset,self.request,view = self)

    def get_paginated_response(自身,数据):

    返回给定
    输出数据的分页样式`Response`对象。

    断言self.paginator不是None
    返回self.paginator.get_paginated_response(data)


  2. 使您的视图集扩展到混合区域,并覆盖 ModelViewSet 的 list()方法

      class MyViewset(MyPaginationMixin,viewsets.ModelViewSet):
    #因为您正在设置分页在设置上,使用以下命令:
    pagination_class = settings.DEFAULT_PAGINATION_CLASS

    def list(self,request,* args,** kwargs):
    response = dict(
    super(MyViewSet,self).list(self,* args,** kwargs..data)

    page = self.paginate_queryset(response ['results]]
    如果页面是不是没有:
    serializer = self.serializer_class(page,many = True)
    return self.get_paginated_response(serializer.data)
    else:
    #这里出问题了...


您当然需要根据自己的需要校准此解决方案,但这会为 ModelViewSet 添加分页。 / p>




对于子问题,@Linovia的评论正确, PAGINATE_BY 已弃用, PAGE_SIZE 是响应页面大小的当前设置。


The DRF docs state that:

Pagination is only performed automatically if you're using the generic views or viewsets.

But I'm using a ModelViewSet which inherits from ViewSet, so I tell myself "Cool, all I have to do is add this to my settings.py":

'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 12, # for 12-col grid css frameworks

However, this didn't work.
If I send a GET request for 27 items it returns all of them (in both the browsable API and json).

  • Am I right in thinking I should only be returned 12?
  • Sub-question: PAGE_SIZE is the number of top-level objects returned per page, right? I saw a few examples with PAGINATE_BY but it doesn't feature in the source so I presume it's deprecated?

I'm using DRF 3.6.3, django 1.11.2.

Edit: my settings:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 12,
}

I've also added pagination_class = PageNumberPagination to the ModelViewSet class, without effect.

Here's the verification from the shell that the Pagination class does know the page size it's supposed to provide:

>>> from rest_framework.pagination import PageNumberPagination
>>> p = PageNumberPagination()
>>> p.max_page_size
>>> print(p.page_size)
12

解决方案

It is true that pagination doesn't work by default on a ModelViewSet despite inheriting from GenericViewSet and the ListMixin. You need to add it manually:

I have composed a Q&A style example which attends that problem and have tested it on a ModelViewSet class.

I will summarize it a bit:

  1. Create a custom mixin to utilize the pagination_class:

    class MyPaginationMixin(object):
        @property
        def paginator(self):
            """
            The paginator instance associated with the view, or `None`.
            """
             if not hasattr(self, '_paginator'):
                 if self.pagination_class is None:
                     self._paginator = None
                 else:
                     self._paginator = self.pagination_class()
             return self._paginator
    
         def paginate_queryset(self, queryset):
             """
             Return a single page of results, or `None` if pagination 
             is disabled.
             """
             if self.paginator is None:
                 return None
             return self.paginator.paginate_queryset(
                 queryset, self.request, view=self)
    
         def get_paginated_response(self, data):
             """
             Return a paginated style `Response` object for the given 
             output data.
             """
             assert self.paginator is not None
             return self.paginator.get_paginated_response(data)
    

  2. Make your viewset extend that mixin and override the list() method of the ModelViewSet:

    class MyViewset(MyPaginationMixin, viewsets.ModelViewSet):
        # since you are setting pagination on the settings, use this:
        pagination_class = settings.DEFAULT_PAGINATION_CLASS
    
        def list(self, request, *args, **kwargs):
            response = dict(
                super(MyViewSet, self).list(self, *args, **kwargs).data)
    
            page = self.paginate_queryset(response['results'])
            if page is not None:
                serializer = self.serializer_class(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                # Something went wrong here...
    

You need to calibrate this solution to your needs of course, but this will add pagination to a ModelViewSet.


For the subquestion, @Linovia 's comment is correct, PAGINATE_BY is deprecated and PAGE_SIZE is the current setting for the response page size.

这篇关于Django Rest Framework全局分页参数不适用于ModelViewSet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆