2015-03-16 23 views
10

Tôi hiện đang có một thiết lập xem API như sau:Pagination trong Django-Rest-Khung sử dụng API-View

class CartView(APIView): 
authentication_classes = [SessionAuthentication, TokenAuthentication] 
permission_classes = [IsAuthenticated, ] 
api_view = ['GET', 'POST'] 

def get(self, request, format=None): 
    try: 
     cart = request.user.cart 
    except Cart.DoesNotExist: 
     cart = Cart.objects.create(user=request.user) 
    cart_details = cart.cart_details.all() 
    serializer = CartDetailSerializer(cart_details, many=True, fields=['id', 'item', 'quantity', 'product_type']) 
    return Response(serializer.data) 

Dưới đây là một CartDetailSerializer ModelSerializer bình thường.

Tôi muốn phân trang API này. Tuy nhiên, trong tài liệu của DRF, tôi thấy điều này:

Nếu bạn đang sử dụng APIView thông thường, bạn cần phải gọi API phân trang để đảm bảo bạn trả lời được phân trang.

Không có ví dụ nào về cách phân trang API APIView thông thường.

Bất kỳ ai cũng có thể đăng một ví dụ mà tôi có thể sử dụng trong kịch bản trên.

Cảm ơn.

Trả lời

9

Khi sử dụng APIView thông thường, bạn cần sử dụng lớp Paginator riêng của Django.

Django Pagination in Views

Trong trường hợp của bạn, bạn có thể đánh số trang queryset trước khi gửi nó cho serializer.

Something như thế này:

def get(self, request, format=None): 
    try: 
     cart = request.user.cart 
    except Cart.DoesNotExist: 
     cart = Cart.objects.create(user=request.user) 
    cart_details = cart.cart_details.all() 

    paginator = Paginator(cart_details, 10) 
    page = request.GET.get('page') 

    try: 
     cart_details = paginator.page(page) 
    except PageNotAnInteger: 
     # If page is not an integer, deliver first page. 
     cart_details = paginator.page(1) 
    except EmptyPage: 
     # If page is out of range (e.g. 9999), deliver last page of results. 
     cart_details = paginator.page(paginator.num_pages) 
    serializer = CartDetailSerializer(cart_details, many=True, fields=['id', 'item', 'quantity', 'product_type']) 
    return Response(serializer.data) 

Hope this helps.

+6

giải pháp này không có, liên kết trang trước tiếp theo và đếm trong các phản ứng. – haudoing

19

Trong khi cách đề cập đến rayy là khả năng, django-rest-framework có thể xử lý nội bộ này bằng một số tính năng bổ sung giúp làm việc với API của bạn dễ dàng hơn nhiều. (Pagination * note django-nghỉ ngơi-framework được xây dựng từ paginator Django từ django.core.paginator)

Ngay sau khi những gì bạn trích dẫn là thông tin quan trọng để giải quyết vấn đề này:

Pagination chỉ được thực hiện tự động nếu bạn đang sử dụng chế độ xem chung hoặc chế độ xem. Nếu bạn đang sử dụng APIView thông thường, bạn sẽ cần tự gọi API phân trang để đảm bảo bạn trả về một câu trả lời được phân trang. Xem mã nguồn cho mixins.ListMixin và generics.GenericAPIView các lớp học cho một ví dụ.

Chỉnh sửa nhẹ những gì được nêu ở đó: xem ListModelMixin.

Nếu bạn đi đến hai liên kết các bạn có thể xem mã nguồn cho các tập tin trên: generics.py mixins.py

Những gì bạn cần làm là bao gồm một cái gì đó như sau để có được pagination để làm việc trong APIView (** Lưu ý: mã này chưa được kiểm chứng nhưng ý tưởng là chính xác. Ngoài ra còn có cách viết tốt hơn thay vì phải bao gồm mã trong mọi chế độ xem nhưng tôi sẽ để nguyên câu trả lời của tôi ngắn gọn và dễ hiểu):

from __future__ import absolute_import 
# if this is where you store your django-rest-framework settings 
from django.conf import settings 
from rest_framework.views import APIView 
from rest_framework.response import Response 

from .models import Cart 

class CartView(APIView): 
    pagination_class = settings.DEFAULT_PAGINATION_CLASS 

    def get(self, request, format=None): 
     #assuming every other field in the model has a default value  
     cart = Cart.objects.get_or_create(user=request.user) 

     #for a clear example 
     cart_details = Cart.objects.all() 

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

     serializer = CartDetailSerializer(cart_details, many=True) 
     return Response(serializer.data) 

    @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) 

Tôi ho pe này đã được giúp đỡ nhiều hơn cho bạn và những người khác đi qua bài đăng này.

+1

Trong khi bạn đúng, đó là câu trả lời được chấp nhận. Việc phân trang DRF chỉ thực hiện phân trang được xây dựng trong django. Kiểm tra mã nguồn tại rest_framework.pagination. Tìm định nghĩa 'paginate_queryset' – ryechus

+0

ryechus bổ sung tuyệt vời. Tôi đã không nhìn vào một phần của mã nguồn nhưng xương sống của phân trang django-rest-framework của chắc chắn được xây dựng trên Django.core.paginator tiêu chuẩn Django. Tôi đã chỉnh sửa câu trả lời trước đó của mình. – prawg

+1

Everyting là không sao, nhưng nó sẽ trả về trang không cart_details, dễ dàng sửa chữa: 'nếu trang không phải là Không: serializer = CartDetailSerializer (trang, nhiều = True)' và phân trang lớp đến từ DRF với 'từ rest_framework.settings nhập khẩu api_settings' và 'pagination_class = api_settings.DEFAULT_PAGINATION_CLASS' – metoikos

0

Tôi đang sử dụng phiên bản DRF 3.6.2. Bạn không cần viết mã quá nhiều. Chỉ cần sử dụng các bước đơn giản này.

class ProductPagination(PageNumberPagination): 
     page_size = 5 

    class product_api(generics.ListCreateAPIView):  
      queryset = Products.objects.all() 
      serializer_class = product_serilizer 
      pagination_class = ProductPagination 

nếu bạn muốn chức năng bằng phương pháp nhận tìm kiếm, bạn có thể viết mã dưới đây

class ProductPagination(PageNumberPagination): 
     page_size = 5 

class product_api(generics.ListCreateAPIView): 
    queryset = Products.objects.all() 
    serializer_class = product_serilizer 
    pagination_class = SearchProductPagination  

    def get_queryset(self): 
     qs = super(product_search_api,self).get_queryset() 
     searched_product = self.request.query_params.get('searched_product',None) 
     if search: 
      qs = Products.objects.filter(Q(product_name__icontains= searched_product)) 
     return qs