본문 바로가기

웹 개발

[Django] Pagination

https://www.django-rest-framework.org/api-guide/pagination/

 

Pagination - Django REST framework

pagination.py Django provides a few classes that help you manage paginated data – that is, data that’s split across several pages, with “Previous/Next” links. — Django documentation REST framework includes support for customizable pagination styl

www.django-rest-framework.org

위에 주소는 DRF에서 사용하는 Pagination에 관한 내용들이 담겨있는 문서 주소이다.

저번에 했던 DRF 프로젝트에서 상품 목록을 조회하는 기능에서 Pagination을 적용할 예정이다.

이번에는 Pagination중 가장 쉬워보이는 PageNumberPagination을 사용하도록 하겠다.

공식 문서에서 보면 PageNumberPagination을 사용하기 위해서 다음과 같이 설정을 해줘야 한다.

# settings.py
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ],
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 5,
}

원래 JWT를 적용했던 부분에서 새로운 설정을 추가해 주도록 하자.

 

다음으로 위의 공식문서에서 밑에 문장을 읽어보면 GenericAPIView에 대한 내용을 찾아서 볼 수가 있는데

class GenericAPIView(views.APIView):
    queryset = None
    serializer_class = None

    # The style to use for queryset pagination.
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

    def get_queryset(self):
        assert self.queryset is not None, (
            "'%s' should either include a `queryset` attribute, "
            "or override the `get_queryset()` method."
            % self.__class__.__name__
        )

        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            # Ensure queryset is re-evaluated on each request.
            queryset = queryset.all()
        return queryset

GenericAPIView는 APIView를 상속받고 있으며 pagination_class로 pagination의 queryset 스타일을 줄 수 있다고 한다.

이제 위에있는 내용을 바탕으로 상품 전체 목록을 pagination해서 보여주는 기능을 구현해보자.

class ProductListAPIView(ListAPIView):
    def get_permissions(self):
        if self.request.method == 'GET':
            return [AllowAny()]
        return [IsAuthenticated()]

    pagination_class = PageNumberPagination
    serializer_class = ProductSerializer

    def get_queryset(self):
        return Product.objects.all().order_by("-pk")

위의 코드는 먼저 ListAPIView를 상속받아서 ProductListAPIView를 만들었는데

pagination_class = PageNumberPagination >>> 데이터가 많을 경우, 데이터를 여러 페이지로 나누어 반환해준다.
serializer_class = ProductSerializer >>> Product 모델의 데이터를 직렬화 해준다.

get_queryset 메소드 >>> product 모델의 모든 오브젝트를 반환하며 pk에 따라서 내림차순으로 정렬해준다.

 

그렇다면 왜 위에서 설명한 GenericAPIView가 아닌 ListAPIView를 상속받아 만든걸까?

class ListAPIView(mixins.ListModelMixin,
                  GenericAPIView):
    """
    Concrete view for listing a queryset.
    """
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

ListAPIView는 GenericAPIView를 상속받아 사용하고 있고 쿼리셋과 시리얼라이저를 기반으로 GET요청이 들어온 데이터를 반환해주기 때문에 사용했다.

위와 같은 방식으로 목록 조회에서 Pagination을 쉽게 구현할 수 있다.

'웹 개발' 카테고리의 다른 글

[Django] 트러블 슈팅 - 1  (0) 2024.09.12
[Django] Django 팀 프로젝트 - 프로젝트 설계  (2) 2024.09.11
[Django] DRF Project - 4  (0) 2024.09.09
[Django] DRF Project - 3  (0) 2024.09.05
[Django] DRF Project - 2  (0) 2024.09.05