[Django] DRF-Pagination

Cherry·2022년 2월 2일
0
post-thumbnail
post-custom-banner

이번 프로젝트에서는 채팅 기반 메모 앱을 만들었다. 메모를 추가하면 할수록 아래 쌓이게 되는데 이 메모들이 100개 혹은 1000개가 넘어가면 전체 메모들을 불러오는데 시간이 굉장히 많이 걸릴 것이다. 그렇게 생각하다가 웹 사이트에서는 일정 수준 이상 쌓이면 다음 페이지로 넘어갈 수 있도록 구현이 되어있는데 앱에서도 충분히 구현가능하다고 생각되어서 페이징을 적용해주기로 했다. 찾아보니 DRF에서 제공해주는 pagination이라는 것이 있어서 사용해 보기로 했다.

DRF에서 제공하는 pagination에는 PageNumberPaginationLimitOffsetPagination 크게 두 가지 방법이 있다.

PageNumberPagination

  • page_size : 한 페이지에 몇 개의 레코드를 보여줄지 표시해준다.

전역 설정을 통한 PageNumberPagination

settings 에서 기본적인 설정을 해줍니다.

어느 pagination을 할 지 결정하고, 그에 대한 parameter 값을 지정한다.

settings.py

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

이렇게 설정해주면 API로 get을 할때 평상시와 다른 응답이 온다.

{
    "count": 5,
    "next": "http://127.0.0.1:8000/post/?page=2",
    "previous": null,
    "results": [
      {
           "id": 1,
          "memo_text": "testingigigi",
          "url": null,
          "tag_id": null,
          "tag_name": null,
          "tag_color": null,
          "images": [],
          "is_marked": false,
          "timestamp": "123456",
          "created_at": "2022-01-09T13:19:37.515511",
          "updated_at": "2022-01-09T13:19:37.515539"
      },
      {
          "id": 2,
          "memo_text": "testingigigi",
          "url": null,
          "tag_id": 5,
          "tag_name": "ㅋㅋ",
          "tag_color": "#F85C5D",
          "images": [],
          "is_marked": false,
          "timestamp": "123456",
          "created_at": "2022-01-09T13:14:51.005294",
          "updated_at": "2022-01-09T13:14:51.005325"
      },
      {
          "id": 3,
          "memo_text": "testtt",
          "url": null,
          "tag_id": 6,
          "tag_name": "Test3",
          "tag_color": "#50B093",
          "images": [],
          "is_marked": false,
          "timestamp": "123456",
          "created_at": "2022-01-09T12:43:55.931403",
          "updated_at": "2022-01-09T12:43:55.931425"
      },
      {
          "id": 4,
          "memo_text": "히히",
          "url": null,
          "tag_id": 5,
          "tag_name": "ㅋㅋ",
          "tag_color": "#F85C5D",
          "images": [],
          "is_marked": false,
          "timestamp": "1641704560",
          "created_at": "2022-01-09T05:02:39.347895",
          "updated_at": "2022-01-09T05:02:39.347935"
      },
      {
          "id": 5,
          "memo_text": "히히",
          "url": null,
          "tag_id": 5,
          "tag_name": "ㅋㅋ",
          "tag_color": "#F85C5D",
          "images": [],
          "is_marked": false,
          "timestamp": "1641704517",
          "created_at": "2022-01-09T05:01:56.066534",
          "updated_at": "2022-01-09T05:01:56.066560"
      }
    ]
}

개별적으로 다른 Pagination

settings 를 통해서 전역적으로 설정을 해주면 모든 view 에 대해서 같은 결과가 나온다. 따라서 각각 개별적으로 설정하는 방법에 대해 알아보도록 하겠다.

우선 pagination.py를 만들어 pagination 설정을 바꿔준다. PageNumberPagination을 상속받고 page_size 도 설정해주면 된다.

pagination.py

from rest_framework.pagination import PageNumberPagination

class MemoPageNumberPagination(PageNumberPagination):
    page_size = 2
    page_size_query_param = 'page_size'
    max_page_size = 1000
  • page_size_query_param : 설정된 경우 사용자가 request 별로 페이지 크기를 설정할 수 있도록하는 쿼리 파라미터의 이름을 나타내는 문자열 값이다. 기본값은 None으로, 사용자가 요청 된 페이지 크기를 제어 할 수 없음을 나타낸다.
  • max_page_size : 설정되면 request 된 최대 페이지 크기를 나타내는 숫자 값입니다. 이 속성은 page_size_query_param도 설정되어있는 경우에만 유효하다.

view 에서는 이를 지정만 해주면 된다.

class MemoViewSet(ModelViewSet):
    queryset = Memo.objects.all()
    serializer_class = MemoSerializer
    pagination_class = MemoPageNumberPagination
 

우선 전역적으로 페이징을 설정해준다음 개별적으로 페이징을 설정하는 방식이 가장 좋다.

LimitOffsetPagination

  • offset : 몇 번째 레코드부터 보여줄 지 설정해준다. (default : 첫 번째 레코드)
  • limit : 몇 개의 레코드를 보여줄 지 설정한다.
  • offset 번째 레코드부터 offset+limit-1 번째 레코드까지 보여준다.

Request:

GET https://api.example.org/accounts/?limit=100&offset=400

Response:

HTTP 200 OK
{
    "count": 1023,
    "next": "https://api.example.org/accounts/?limit=100&offset=500",
    "previous": "https://api.example.org/accounts/?limit=100&offset=300",
    "results": [
       …
    ]
}

전역 설정을 통한 LimitOffsetPagination

전체적으로 PageNumberPagination와 비슷하다.
settings.py

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}

LimitOffsetPagination는 많이 쓰이지 않으니 여기까지만 알고 있으면 될 것 같다.

post-custom-banner

0개의 댓글