- 각 함수 및 템플릿에 페이지네이션 코드 추가하기
상황: 각 페이지에서 페이지네이션 외에 분류, 정렬 등 다른 매개변수를 사용해야 하는 경우, 캡슐화된 라이브러리를 사용하는 것은 권장하지 않습니다.
1단계: 페이지네이션이 필요한 views에 다음 코드를 추가합니다:
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
def get_user_courses(request):
user_courses = UserCourse.objects.filter(study_man=request.user)
course_list = [item.study_course for item in user_courses]
# 페이지네이션 처리 코드
page_num = request.GET.get('page', '1')
paginator = Paginator(course_list, 8)
try:
page_obj = paginator.page(page_num)
except PageNotAnInteger:
page_obj = paginator.page(1)
except EmptyPage:
page_obj = paginator.page(paginator.num_pages)
return render(request, 'users/usercenter-mycourse.html', {
'course_list': course_list,
'page_obj': page_obj,
'type': 'course'
})
2단계: 템플릿에 다음 HTML 코드를 추가합니다:
<!-- 기존 루프: 모든 데이터 반환 -->
{% for course in course_list %}
<!-- 다음과 같이 변경 -->
{% for course in page_obj %}
<!-- 페이지네이션 영역에 추가 -->
<div class="pageturn">
{% if page\_obj.has\_previous %} - [이전 페이지](<?page={{ page_obj.previous_page_number }}>)
{% endif %} {% for num in page\_obj.paginator.page\_range %} {% if num == page\_obj.number %} - [{{ num }}](<?page={{ num }}>)
{% else %} - [{{ num }}](<?page={{ num }}>)
{% endif %} {% endfor %} {% if page\_obj.has\_next %} - [다음 페이지](<?page={{ page_obj.next_page_number }}>)
{% endif %}
</div>
이렇게 하면 기본적인 페이지네이터가 완성됩니다. 하지만 대부분의 경우 웹사이트에서 페이지네이션 시 정렬과 분류가 필요합니다. 이때 views에서 정렬, 분류 코드를 페이지네이션 코드 전에 작성해야 하며, 페이지네이션 시 정렬과 분류 값이 유지되도록 템플릿에 전달해야 합니다.
def course_list(request):
all_courses = CourseInfo.objects.all().order_by('-add_time')
popular_courses = all_courses.order_by('-love_num')[:3]
current_sort = 'add_time'
# 분류 및 정렬 작업은 페이지네이션 전에 처리
current_sort = request.GET.get('sort')
if not current_sort:
current_sort = 'add_time'
page_num = request.GET.get('page', '1')
keywords = request.GET.get('keywords', '')
if keywords:
all_courses = all_courses.filter(
Q(name__icontains=keywords) |
Q(desc__icontains=keywords) |
Q(detail__icontains=keywords)
)
if current_sort:
all_courses = all_courses.order_by('-' + current_sort)
paginator = Paginator(all_courses, 9)
try:
page_obj = paginator.page(page_num)
except PageNotAnInteger:
page_obj = paginator.page(1)
except EmptyPage:
page_obj = paginator.page(paginator.num_pages)
# 정렬 및 분류 값을 템플릿에 전달해야 페이지네이션 시 유지됨
return render(request, 'courses/course-list.html', {
'all_courses': all_courses,
'popular_courses': popular_courses,
'base_type': 'course',
'current_sort': current_sort,
'page_obj': page_obj,
'keywords': keywords
})
对应的 HTML 也需要 변경됩니다:
{% if page\_obj.has\_previous %} - [이전 페이지](<?page={{ page_obj.previous_page_number }}&sort={{ current_sort }}>)
{% endif %} {% for num in page\_obj.paginator.page\_range %} {% if num == page\_obj.number %} - [{{ num }}](<?page={{ num }}&sort={{ current_sort }}>)
{% else %} - [{{ num }}](<?page={{ num }}&sort={{ current_sort }}>)
{% endif %} {% endfor %} {% if page\_obj.has\_next %} - [다음 페이지](<?page={{ page_obj.next_page_number }}&sort={{ current_sort }}>)
{% endif %}
이렇게 하면 다른 매개변수가 있는 페이지네이션 작업이 완료됩니다.
2. 여러 페이지에서 단순한 페이지네이션만 필요하거나 다른 매개변수가 동일한 경우, 페이지네이션을 클래스로 캡슐화하여 사용할 수 있습니다
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
class PaginationHelper(Paginator):
def __init__(self, request, object_list, per_page):
Paginator.__init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True)
page_num = request.GET.get('page', '1')
paginator = Paginator(object_list, per_page)
try:
page_obj = paginator.page(page_num)
except PageNotAnInteger:
page_obj = paginator.page(1)
except EmptyPage:
page_obj = paginator.page(paginator.num_pages)
page_html_parts = ['<div class="pageturn">'\] if page\_obj.has\_previous(): page\_html\_parts.append( '- [이전 페이지](?page={})
'.format(page\_obj.previous\_page\_number) ) for num in page\_obj.paginator.page\_range: if num == page\_obj.number: page\_html\_parts.append( '- [{}](?page={})
'.format(num, num) ) else: page\_html\_parts.append( '- [{}](?page={})
'.format(num, num) ) if page\_obj.has\_next(): page\_html\_parts.append( '- [다음 페이지](?page={})
'.format(page\_obj.next\_page\_number) ) page\_html\_parts.append('</div>')
self.page_html = ''.join(page_html_parts)
self.page_obj = page_obj
사용할 때는 필요한 views에서 함수를 가져오기만 하면 됩니다:
# 페이지네이션 기능
# 페이지네이션할 목록을 all_orgs로, 페이지당 데이터 수를 3으로 변경
pagination = PaginationHelper(request, all_orgs, 3)
return render(request, 'orgs/org-list.html', {
'all_orgs': all_orgs,
'page_obj': pagination.page_obj,
'page_html': pagination.page_html
})
해당 HTML에서 한 줄의 코드만 추가하면 됩니다:
<!-- 기존 루프: 모든 데이터 반환 -->
{% for course in course_list %}
<!-- 다음과 같이 변경 -->
{% for course in page_obj %}
<!-- 페이지네이션 영역에 추가 -->
{{ page_html|safe }}