djando REST framework Pagination
django Rest Freamwork에서 pagination을 처리하는 방법은 여러 가지가 있다.
https://www.django-rest-framework.org/api-guide/pagination/
여기 참고 하길 .. 근데 나는 읽어도 무슨 소린지 한참 봐야 했다. 개발은 방법이 너무 다양해서 그 많은 방법 중에 하나를 고르는 게 어려운 듯.. ㅎㅎ 아무튼,.
먼저 settings.py에 아래 부분을 추가한다. LimitOffsetPagination을 사용하려고 했는데 페이지 번호를 지정하는 법을 몰라서 PageNumberPagination을 사용했다.
eg) 두번째 페이지 주세요. => LimitOffsetPagination을 이용해서 어떻게 하는지 모르겠어서
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination'
# 나는 LimitOffsetPagination 대신 PageNumberPagination을 사용했다.
}
settings.py 에 `PAGE_SIZE` 를 global로 정의할 수 도 있지만 customising 하고 싶다면 따로 클래스를 만들면 된다.
나는 대시보드에서는 리스트 사이즈가 5개, 그냥 일반 리스트에서는 사이즈를 20개씩 불러오기 때문에 이렇게 클라스를 만들어봤다.
# pagination.py
class DashboardPageNumberPagination(PageNumberPagination):
page_size = 5
# 여기서 다른 값들도 설정 가능.. 난 일단 사이즈만 정하겠음
class ListPageNumberPagination(PageNumberPagination):
page_size = 20
url : /api/lang/categories?page_size=5 위 url은 아래 view를 부른다.dddd/categories/?page_size=5/api/lang/categories/?page_size=
# view.py
@api_view(['GET'])
def get_categories(request):
try:
page_size = 20
if 'page_size' in request.query_params:
page_size = request.query_params['page_size']
categories = Category.objects.filter()
# paging
if int(page_size) == 5:
paginator = DashboardPageNumberPagination() # 여기서 아까 만들었던 클라스를 사용한다.
else:
paginator = ListPageNumberPagination() # 리스트니깐 20개씩 불러온다.
context = paginator.paginate_queryset(categories, request) # 불러온 데이터를 paginator.paginate_queryset 하니깐 page_size 만큼 만 보여진다
paging = get_pagination_result(paginator, categories.count()) # 내가 만든 페이지 객체
serializer = CategorySerializer(context, many=True) # serialize 한다
res = {
'page': paging,
'data': serializer.data
}
return JsonResponse(res, safe=False) # response 반환
except Category.DoesNotExist:
return HttpResponse(status=404)
# pagination.py
def get_pagination_result(paginator, total_items):
items_per_page = paginator.page_size
current_page = paginator.page.number
return {
'items_per_page': items_per_page, # 한 페이지에 보여지는 갯수 (나는 20 or 5)
'current_page': current_page, # 현재 페이지 (default 1)
'total_items': total_items # 총 아이템 개수
}
url : /api/lang/categories? page_size=5에 대한 Response는 이렇게 받는다.
두 번째 페이지를 불러오고 싶다면 url 은?
url : /api/lang/categories? page_size=5&page=2를 사용한다. 여기서 page라는 값을 사용해야
context = paginator.paginate_queryset(categories, request) - paginate_queryset에서 page라는 값을 default로 사용하게 되어있다.
바꾸는 방법은 있겠지만 난 그냥 있는 대로 쓰겠어요 ^_^
Response는 이렇게 온다. page 부분은 내가 만든 것. UI에서 저렇게 받으면 편하기 때문에..
서버는 이렇게 처리했음.. 그럼 UI에서는?
angular에서 ngx-pagination 이용해서 paging 처리하기
paging component는 ngx-pagination을 사용했다.
https://github.com/michaelbromley/ngx-pagination#readme
먼저 설치부터 한다,
npm install ngx-pagination --save
사용하는 모듈에서 import를 해준다. 나는 languageModule에서 사용하겠다. imports 안에 불러온다.
서버에서 보낸 response를 보면 아래 html을 이해하기 쉬울 것이다.
response 안에 data와 page 가 있다. data 안에는 category list 가 있고 page 안에는 paging 정보가 들어있다.
language.html
<ul class="list-group list-group-flush" *ngFor="let i of categories['data'] | paginate:
{ id: 'category',
itemsPerPage: categories['page']['items_per_page'],
currentPage: categories['page']['current_page'],
totalItems: categories['page']['total_items']
}"
>
<li class="list-group-item"><a href="javascript:" (click)="onClickCategory(i.id)">{{i.name}}</a></li>
</ul>
<pagination-controls id="category" (pageChange)="pageChanged($event)"></pagination-controls>
<!-- 1. ul에서 list를 for문으로 돌 때 paginate directive 를 사용한다.
2. directive 안에 id 를 고유한 값으로 정한다. 나는 category 를 사용했다.
3. itemsPerPage : 한 페이지에 몇 개의 아이템을 보여줄 것 인가.
4. currentPage: 현재 페이지는 몇번인가
5. totalItems: 총 아이템은 몇개인가
6. <pagination-controls> 부분이 페이징 컨트롤 html 부분이다
7. paginate directive 에 지정한 id를 <pagination-controls> 여기 id로 지정한다.
8. (pageChange)는 1,2,3, ... 을 클릭했을 때 페이지를 이동할 때 여기를 탄다
-->
위에 부분이 이 페이징 컨트롤을 말한다.
// language.component.ts
// category list 불러오는 메소드
getCategories(page: number = 1, search_text?:string) {
this.langService.getCategories(this.page_size, page, search_text).subscribe((result) => {
this.categories = result;
})
}
// next or prev 페이지를 불러오는 함수 - data 는 숫자이다.
// 예) 페이징 컨트롤에서 1을 클릭하면 1, 4페이지를 클릭하면 4를 말한다.
pageChanged(data) {
this.getCategories(data);
}
url : api/lang/categories?page_size=5
url : api/lang/categories?page_size=5&page=2
이렇게 페이징 처리를 완료했다. 참 어렵구나 ^_^
'개발이나하자.. > backend' 카테고리의 다른 글
[django] 파이썬 장고 BeautifulSoup 이용한 웹 크롤링 연습 (0) | 2020.08.25 |
---|---|
[django] django rest framework 로그인 과정 | 장고 로그인 | 인증 | 토근 발행 (0) | 2020.03.06 |