2015-08-03 154 views
13

我有一個視圖集中這樣一個列出用戶的數據:Django的REST框架:打開分頁上一個視圖集(如ModelViewSet分頁)

class Foo(viewsets.ViewSet): 

    def list(self, request): 
     queryset = User.objects.all() 
     serializer = UserSerializer(queryset, many=True) 
     return Response(serializer.data) 

我想打開分頁像ModelViewSet默認分頁:

{ 
    "count": 55, 
    "next": "http://myUrl/?page=2", 
    "previous": null, 
    "results": [{...},{...},...,{...}] 
} 

The official doc說:

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

...但我的結果集我根本沒有分頁。我如何分頁?

回答

16

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

第一個路障是將文檔翻譯成英文。他們打算傳達的是你想要一個通用的視圖集。通用視圖集擴展自generic ApiViews,它們具有額外的類方法用於對查詢集和響應進行分頁。

此外,你提供你自己的list方法,但默認分頁過程實際上是由mixin處理:

class ListModelMixin(object): 
    """ 
    List a queryset. 
    """ 
    def list(self, request, *args, **kwargs): 
     queryset = self.filter_queryset(self.get_queryset()) 

     page = self.paginate_queryset(queryset) 
     if page is not None: 
      serializer = self.get_serializer(page, many=True) 
      return self.get_paginated_response(serializer.data) 

     serializer = self.get_serializer(queryset, many=True) 
     return Response(serializer.data) 

最簡單的辦法,用框架代碼:

class Foo(mixins.ListModelMixin, viewsets.GenericViewSet): 
    queryset = User.objects.all() 
    serializer = UserSerializer 

更復雜的解決方案是,如果您需要自定義list方法,那麼您應該按照您認爲合適的方式編寫它,但採用上述mixin代碼片段的樣式。

3

嘗試提供一個類變量

paginate_by = 10 #This will paginate by 10 results per page. 

創建自定義ViewSet僅執行list操作的情況下,這裏現在。

class ListModelViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): 
    pass 

現在繼承你Foo類此定製的視圖集中

class Foo(ListModelViewSet): 

    paginate_by = 10 

    def list(self, request): 
     queryset = User.objects.all() 
     serializer = UserSerializer(queryset, many=True) 
     return Response(serializer.data) 

這會幫助你獲得分頁工作。

+0

我接着說:paginate_by = 10',但它不工作。如果我用class Foo(generics.ListCreateAPIView)更改class Foo(viewsets.ViewSet):'我得到這個錯誤:_as_view()需要1個參數(給出3)_ – floatingpurr

+1

您是否將任何參數傳遞給.as_view ()?其次爲什麼你不使用'ModelViewSet'? –

+0

不,沒有.as_views()。我沒有使用'ModelViewSet',因爲我需要編寫一些邏輯來過濾我的'queryset'的一個子集,並將一些數據添加到與用戶模型無關的結果集(該邏輯在我的問題的代碼中被省略) – floatingpurr

17

對於那些使用DRF 3.1或更高版本的用戶,他們正在改變處理分頁的默認方式。有關詳細信息,請參見http://www.django-rest-framework.org/topics/3.1-announcement/

現在,如果要啓用分頁的ModelViewSet你可以做到在全球範圍通過在settings.py文件設置:

REST_FRAMEWORK = { 
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 
    'PAGE_SIZE': 100 
} 

或者,如果你只是希望它爲一個ModelViewSet您可以手動設置pagination_class僅用於該視圖。

from rest_framework.pagination import PageNumberPagination 

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

class FooViewSet(viewsets.ModelViewSet): 
    pagination_class = StandardResultsSetPagination 

這也可以讓你調整分頁處理的方式只爲該視圖集。

DRF 3.1還引入了可以使用的默認分頁方案的新類型,如LimitOffset和Cursor。使用viewsets和列表

+0

我試過了,但是沒有工作 –

+0

如果你使用PageNumberPagination來請求page1,然後新建一個em被添加到列表中,然後您請求page2,剛剛在page1中獲得的最後一個項目將作爲page2中的第一個項目再次顯示(顯示爲連續兩次)。 CursorPagination比PageNumberPagination更受推薦。 CursorPagination保持對象的引用,並且不必爲每個頁面計算內容。有關實現,請參閱https://stackoverflow.com/a/47657610/5881884 – DevB2F

1

分頁中DRF

在這裏,我已經處理了異常,如果頁面是空的,它會顯示空記錄

在設置定義頁面大小,該頁面大小是全球性的,它是用來通過在視圖

rEST_FRAMEWORK = { 'PAGE_SIZE':10,} paginator_queryset

鑑於 從rest_framework進口混入,viewsets

class SittingViewSet(viewsets.GenericViewSet, 
    mixins.ListModelMixin): 

    serializer_class = SittingSerializer 
    queryset = Sitting.objects.all() 
    serializer = serializer_class(queryset, many=True) 

    def list(self, request, *args, **kwargs): 
     queryset =self.filter_queryset(Sitting.objects.all().order_by('id')) 

     page = request.GET.get('page') 

     try: 
      page = self.paginate_queryset(queryset) 
     except Exception as e: 
      page = [] 
      data = page 
      return Response({ 
       "status": status.HTTP_404_NOT_FOUND, 
       "message": 'No more record.', 
       "data" : data 
       }) 

     if page is not None: 
      serializer = self.get_serializer(page, many=True) 
      data = serializer.data 
      return self.get_paginated_response(data) 

     # serializer = self.get_serializer(queryset, many=True) 
     return Response({ 
      "status": status.HTTP_200_OK, 
      "message": 'Sitting records.', 
      "data" : data 
     }) 

**>注意:如果你不使用ORDER_BY它會顯示異常,因爲這個名單

給無序列表**

+0

您也可以訪問https://stackoverflow.com/a/46173281/8231158我給了兩個答案一個對象Viewset和其他API視圖。 –

相關問題