简体   繁体   English

在Django Rest Framework中定义分页page_size per-view

[英]Define pagination page_size per-view in Django Rest Framework

Since version 3.3 it's not longer possible to define page_size on the view, as it's moved to the paginator class. 从版本3.3 ,不再可能在视图上定义page_size,因为它已移至paginator类。 related deprecations 相关的弃用

Our API has different page_sizes defined for different views and it feels ambiguous to add new paginator subclasses just to overwrite the page_size attribute. 我们的API为不同的视图定义了不同的page_sizes,添加新的paginator子类只是为了覆盖page_size属性感觉不明确。 I cannot instantiate the paginator class in the view definition and use the __init__ method as it's instantiated here . 我无法在视图定义中实例化paginator类,并使用__init__方法,因为它在此处实例化。 I could overwrite this and make it a method what returns an instance instantiated with the right parameters, but as its name is not get_pagination_class , probably it's not a good idea. 我可以覆盖它并使它成为一个方法,返回一个用正确的参数实例化的实例,但由于它的名字不是get_pagination_class ,可能它不是一个好主意。

My question is what would be the cleanest way to dynamically create a paginator class with the proper page_size attribute set? 我的问题是什么是动态创建具有正确的page_size属性集的paginator类最干净的方法?

I've seen this question, and I'd like to avoid both of its solutions. 我已经看到了这个问题,我想避免它的两个解决方案。

You can achieve something relatively clean: 你可以实现相对干净的东西:


  • Assuming you are setting the pagination per class with the pagination_class attribute. 假设您使用pagination_class属性设置每个类的pagination_class
  • Assuming that you keep the page_size attribute in your class. 假设您在类中保留了page_size属性。

  1. In your settings.py add a global pagination setting: 在您的settings.py添加全局分页设置:

     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': default_page_size, 

    You can handle with this all the views that have the same page size. 您可以处理具有相同页面大小的所有视图。

  2. For any other view/viewset: 对于任何其他视图/视图集:

     class ACustomViewSet(mixins.ListModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): pagination_class = PageNumberPagination page_size = N pagination_class.page_size = self.page_size 

    Or you can do this inside a method: 或者您可以在方法中执行此操作:

     def list(self, request, *args, **kwargs): self.pagination_class.page_size = self.page_size ... 

I finally ended up with customizing it in a custom pagination. 我最终最终定制了自定义分页。 It seemed like the most neat and least hacky solution. 这似乎是最简洁,最不讨厌的解决方案。

The custom pagination 自定义分页

from rest_framework import pagination

class CustomPageNumberPagination(pagination.PageNumberPagination):
    """Custom page number pagination."""

    page_size = 30
    max_page_size = 10000
    page_size_query_param = 'page_size'

    def get_page_size(self, request):
        """Get page size."""
        # On certain pages, force custom/max page size.
        try:
            view = request.parser_context['view']
            if view.action in [
                'custom_page_size_view_1',
                'custom_page_size_view_2',
                # ...
                'custom_page_size_view_n',
            ]:
                return self.max_page_size
        except:
            pass

        return super(CustomPageNumberPagination, self).get_page_size(request)

The view 风景

from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import list_route
from .pagination import CustomPageNumberPagination

class MyView(ModelViewSet):

    pagination_class = CustomPageNumberPagination

    @list_route()
    def custom_page_size_view_1(self, request):
        """Custom page size view 1"""

    @list_route()
    def custom_page_size_view_2(self, request):
        """Custom page size view 2"""

    @list_route()
    def custom_page_size_view_3(self, request):
        """Custom page size view 3"""

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM