Django休息框架:如何在ModelViewSet中关闭/打开分页

时间:2017-06-05 13:36:19

标签: django csv pagination django-rest-framework

我正在使用Django REST framework djangorestframework-csvhttps://github.com/sameersbn/docker-gitlab默认分页设置,但是当请求格式为“CSV”时,就不需要paginaion。可以通过以下方式禁用分页:

pagination_class = None

可以动态更改它吗?

class ObjectViewSet(BaseViewSet, viewsets.ModelViewSet):

    queryset = Object.objects.none()
    serializer_class = ObjectSerializer
    pagination_class = None # if format is "CSV"
    # pagination_class = None # if fromat isn't "CSV"

感谢。

7 个答案:

答案 0 :(得分:7)

一种选择是通过设置no_page查询参数来动态禁用视图上的分页:

def paginate_queryset(self, queryset, request, view=None):
    if 'no_page' in request.query_params:
        return None

    return super().paginate_queryset(queryset, request, view)

答案 1 :(得分:4)

此解决方案对我有用

DRF版本:3.11.0

Django版本:2.2.7

默认情况下,分页功能有效,但是当我通过查询参数'no_page'时,分页功能将被禁用: 像:http://localhost:8000/api/city/?no_page

class CityListView(generics.ListCreateAPIView):
    serializer_class = serializers.CitySerializer
    def paginate_queryset(self, queryset, view=None):
        if 'no_page' in self.request.query_params:
            return None
        else:
            return self.paginator.paginate_queryset(queryset, self.request, view=self)

答案 2 :(得分:3)

如果您只想动态地打开或关闭客户端的分页,您可以自定义分页类:

class Pagination(PageNumberPagination):
    page_size_query_param = 'page_size'
    max_page_size = 100

    def get_page_size(self, request):
        if self.page_size_query_param:
            page_size = min(int(request.query_params.get(self.page_size_query_param, self.page_size)),
                        self.max_page_size)
            if page_size > 0:
                return page_size
            elif page_size == 0:
                return None
            else:
                pass
        return self.page_size

使用此类作为您的pagination_class,您可以按请求url“http://www.example.com/some_object/?page_size=0”关闭分页,?page_size = 0将禁用分页。 如果您只是想在请求格式为CVS时禁用分页,您可以尝试danilke所说的。

答案 3 :(得分:2)

它不再起作用了(至少在最新版本中不起作用),您应该做类似的事情

 def paginate_queryset(self, queryset, request, view=None):
     if 'page' not in request.query_params:
            return queryset
     return super().paginate_queryset(queryset)

并在列表方法内使用self.paginate_queryset(queryset, request)调用函数

答案 4 :(得分:1)

您只需在类中使用 # changed name as you are finding a single category @category = Category.find(params[:category_id]) # initiate a new task first: @task = Task.new(category: @category) if @task.valid? @task.save else @task.errors end

pagination_class = None

答案 5 :(得分:0)

解决方案是:

class PaginatedCSVRenderer (CSVRenderer):
    results_field = 'results'

    def render(self, data, *args, **kwargs):
        if not isinstance(data, list):
            data = data.get(self.results_field, [])
        return super(PaginatedCSVRenderer, self).render(data, *args, **kwargs)

而不是:

class ObjectViewSet(BaseViewSet, viewsets.ModelViewSet):

    queryset = Object.objects.none()
    serializer_class = ObjectSerializer
    renderer_classes =  (JSONRenderer, PaginatedCSVRenderer)

并从设置中删除:

   'PAGE_SIZE': 10,

答案 6 :(得分:0)

也许是一种更具前瞻性的方法-打开my_venv/lib/python3.8/site-packages/rest_framework/generics.py-替换my_venv和您的Python版本,滚动到第165行左右并复制paginate_queryset的方法签名。还要检查它返回的内容if self.paginator is None-如果要禁用分页,则返回的内容。

在DRF 3.11上,父方法签名为paginate_queryset(self, queryset),而if self.paginator is None返回None,所以我使用了:

def paginate_queryset(self, queryset):
    if 'page_id' in self.request.query_params:
        return None
    return super().paginate_queryset(queryset)

我还没有测试过,但是我猜想OP问题的答案是(假设一个相当默认的DRF配置):

if ('format' in self.request.query_params and 
        self.request.query_params['format'] == 'csv'):