【问题标题】:Django Rest 'PageNumberPagination' object has no attribute 'page' errorDjango Rest 'PageNumberPagination' 对象没有属性 'page' 错误
【发布时间】:2022-02-07 23:18:05
【问题描述】:

我有一个基于函数的 Django API,如本示例所示:

@api_view(['GET'])
def findData(request):
    dataId = request.GET['dataId']
    page_query_param = 'page'
    page_size = request.GET['page_size']
    paginator = PageNumberPagination()
    paginator.page_size = page_size
    paginator.page_query_param = page_query_param
    qry_set = Data.objects.all()
    serializer = dataIdSerializer(qry_set, many=True)
    theData= serializer.data
    return Response(paginator.get_paginated_response(theData))

但我不断收到此错误:

AttributeError: 'PageNumberPagination' object has no attribute 'page'

我试过设置

paginator.page_query_param = page_query_param

但还是同样的问题。请告知如何解决。

谢谢

【问题讨论】:

  • 您是否有理由使用普通视图,而不仅仅是 DRF 的 APIView(可以自动处理此问题)?
  • 其实是的。我正在从 C# rest 移植 API;并且前端 UI(在我的控制之外)基本上是在调用端点 findData。我已经有数据的 ViewSet,但我必须使用 /findData 端点。请告知是否有使用 findData + APIView、ViewSet 或泛型的方法...如果需要,我可以使用所有方法,我只需要使用 UI 的 findData 端点仍然可以工作。谢谢
  • dataId 到底在做什么?看起来你“扔掉”了那个变量?
  • 对不起,它是一个过滤器......我使用 .all 简化了示例,但真正的 qry 应用了一个过滤器(qry 参数)
  • 现在看起来你只是对所有Data对象进行分页,所以一个简单的ListAPIView就足够了。

标签: django django-rest-framework


【解决方案1】:

问题是page 在调用.paginate_queryset() 时设置在PageNumberPagination 上。

因此,您需要在您的paginator 上调用.paginate_queryset() 并传递querysetrequest

当你实例化你的序列化器时,传递你调用.paginate_queryset()而不是qry_set得到的结果

完成后,DRF 将抛出另一个异常,因为您将 paginator.get_paginated_response(theData) 放入 Response。要解决这个问题,只需返回 paginator.get_paginated_response(theData)

最后您的代码将如下所示:

def findData(request):
    dataId = request.GET['dataId']
    page_query_param = 'page'
    page_size = request.GET['page_size']
    paginator = PageNumberPagination()
    paginator.page_size = page_size
    paginator.page_query_param = page_query_param
    qry_set = Data.objects.all()
    p = paginator.paginate_queryset(queryset=qry_set, request=request) # change 1
    serializer = dataIdSerializer(p, many=True) # change 2
    theData= serializer.data
    return paginator.get_paginated_response(theData) # change 3

【讨论】:

  • 非常感谢您的回答为我节省了很多时间
【解决方案2】:

使用ListView 可能更有效,这不仅会删除大量样板代码,而且可能更不容易出错。您可以将分页器子类化为您自己的:

class MyPaginator(PageNumberPagination):
    page_size = 100
    page_size_query_param = 'page_size'
    max_page_size = 1000

那么在ListView中,我们可以利用MyPaginator

from rest_framework import generics

class DataListView(generics.ListAPIView):
    queryset = Data.objects.all()
    serializer_class = dataIdSerializer
    pagination_class = MyPaginator

    def get_queryset(self, *args, **kwargs):
        dataId = self.request.GET['dataId']
        super().get_queryset(*args, **kwargs).filter(
            # …
        )

您可以在此处过滤get_queryset 方法中的查询集,以仅使用满足给定条件的Data 对象。

在网址中,您最终可以将其与.as_view() 链接:

urlpatterns = [
    path('/findData', DataListView.as_view())
]

【讨论】:

    【解决方案3】:

    对我来说,将此添加到 settings.py 解决了这个问题。

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 10    # the size of one page
    }
    

    【讨论】:

      猜你喜欢
      • 2022-09-23
      • 2020-07-03
      • 2020-08-21
      • 2017-01-22
      • 2022-09-28
      • 2021-10-09
      • 2016-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多