[Python] django 게시판 페이징 처리
페이징이란 게시판 등과 같은 글의 목록 등을 구간 별로 나누어 페이지 형태로 보여주는 작업을 말하는 것입니다.
게시판의 페이징 처리가 안되어 있으면 있는 모든 게시물이 한 페이지에 출력되어 스크롤바가 엄청 길어지는 현상이 나타납니다.
지금까지 구현한 질문 목록은 현재 페이징 처리가 안되어 있기 때문에 게시물 300개를 작성하면 한 페이지에 300개의 게시물이 모두 표시됩니다.
확인을 위해 실제로 대량의 데이터를 만들어 보겠습니다.
다음처럼 명령프롬프트(cmd) 창에서 장고 셸을 실행합니다.
>python manage.py shell
질문 데이터를 생성하기 위한 모듈을 임포트 합니다.
>>>from pybo.models import Question
>>>from django.utils import timezone
그리고 다음과 같이 300개의 테스트 데이터를 생성합니다.
>>> for i in range(300):
... q = Question(subject='테스트 데이터:[%03d]' % i, content='내용무', create_Date=timezone.now())
... q.save()
...
>>>
q.save() 까지 입력하시고 Enter 키 누르시고 ... 옆에 아무것도 없는 곳에서 Enter 키를 한번 더 누르면 명령문이 실행됩니다.
300개의 데이터가 처리되는데 약 1초 정도 소요되니 기다리시면 >>> 가 나오면서 명령어 처리가 끝이납니다.
이제 http://localhost:8000/pybo 페이지를 확인하시면 아래와 같이 데이터를 확인하실 수 있습니다.
300개의 데이터가 한 화면에 전부 보여지는 것을 확인하실 수 있습니다. 이제 페이징 처리를 하여 페이지에 번호를 매겨 깔끔하게 정리해 보겠습니다.
페이징 처리
장고에서는 페이징 처리를 위한 Paginator 클래스를 제공합니다.
데이터 처리를 위한 views.py 을 다음과 같이 수정합니다.
mysite\pybo\views.py
from django.utils import timezone
from .forms import QuestionForm
from django.core.paginator import Paginator #(추가)
def index(request):
page = request.GET.get('page', '1') #페이지 (추가)
question_list = Question.objects.order_by('-create_date')
paginator = Paginator(question_list, 10) #페이지당 10개씩 보여주기 (추가)
page_obj =- paginator.get_page(page) #(추가)
context = {'question_list': page_obj} #(수정)
return render(request, 'pybo/question_list.html', context)
from django.core.paginator
Paginator 사용을 위해 import 해 주었다.
page = request.GET.get('page', '1')
http://localhost:8000/pybo/?page=1 처럼 GET 방식으로 호출된 URL에서 page 값을 가져올 때 사용합니다.
만약 http://localhost:8000/pybo 처럼 page 값 없이 호출된 경우에는 디폴트로 1이라는 값을 설정합니다.
그리고 Paginator 클래스를 다음처럼 사용합니다.
paginator = Paginator(question_list, 10)
첫 번째 파라미터 question_list는 게시물 전체를 의미하는 데이터이고
두 번째 파라미터 10은 페이지당 보여줄 게시물의 개수입니다.
page_obj = paginator.get_page(page)
그리고 paginator를 이용하여 요청된 페이지(page)에 해당되는 페이징 객체(page_obj)를 생성합니다.
이렇게 하면 장고 내부적으로는 데이터 전체를 조회하지 않고 해당 페이지의 데이터만 조회하도록 쿼리가 변경됩니다.
위와 같이 설정하시고 http://localhost:8000/pybo 페이지를 새로고침하시면 아래와 같이 10개의 데이터만 조회된 것을 확인하실 수 있고 아직 페이지를 나타내는 숫자는 안보이는 것을 확인하실 수 있습니다.
페이징 객체 page_obj 속성
항목 | 설명 |
paginator.count | 전체 게시물 개수 |
paginator.per_page | 페이지당 보여줄 개시물 개수 |
paginator.page_range | 페이지 범위 |
number | 현재 페이지 번호 |
previous_page_number | 이전 페이지 번호 |
next_page_number | 다음 페이지 번호 |
has_previous | 이전 페이지 유무 |
has_next | 다음 페이지 유무 |
start_index | 현재 페이지 시작 인덱스(1부터 시작) |
end_index | 현재 페이지의 끝 인덱스(1부터 시작) |
템플릿에 페이징 적용하기
데이터 변경은 끝났으니 이제 화면에 보이는 템플릿을 수정할 차례입니다.
페이지 숫자 처리를 위해 아래와 같이 코드를 수정하십시오.
mysite\templates\pybo\question_list.html
</table> 태그 아래에 입력하시면 됩니다.
(... 생략 ...)
</table>
<!-- 페이징처리 시작 -->
<ul class="pagination justify-content-center">
<!-- 이전페이지 -->
{% if question_list.has_previous %} <!-- 이전 페이지가 있는지 체크 -->
<li class="page-item">
<a class="page-link" href="?page={{ question_list.previous_page_number }}">이전</a> <!-- 이전 페이지 번호로 이동 -->
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" tabindex="-1" aria-disabled="true" href="#">이전</a>
</li>
{% endif %}
<!-- 페이지리스트 -->
{% for page_number in question_list.paginator.page_range %} <!-- 페이지 리스트 루프 -->
{% if page_number >= question_list.number|add:-5 and page_number <= question_list.number|add:5 %} <!-- 페이지 번호 표시 제한 -->
{% if page_number == question_list.number %} <!-- 현재 페이지와 같은지 체크 -->
<li class="page-item active" aria-current="page">
<a class="page-link" href="?page={{ page_number }}">{{ page_number }}</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ page_number }}">{{ page_number }}</a>
</li>
{% endif %}
{% endfor %}
<!-- 다음페이지 -->
{% if question_list.has_next %} <!-- 다음 페이지 번호가 있는지 체크 -->
<li class="page-item">
<a class="page-link" href="?page={{ question_list.next_page_number }}">다음</a> <!-- 다음 페이지 번호로 이동 -->
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" tabindex="-1" aria-disabled="true" href="#">다음</a>
</li>
{% endif %}
</ul>
<!-- 페이징처리 끝 -->
<a href="{% url 'pybo:question_create' %}" class="btn btn-primary">질문 등록하기</a>
</div>
{% endblock %}
이전 페이지가 있는 경우 "이전" 링크에 활성화되게 하였습니다.
이전 페이지가 없는 경우 "이전" 링크가 비활성화 되도록 하였습니다.
다음 페이지도 마찬가지 입니다.
그리고 페이지 리스트를 루프 돌면서 해당 페이지로 이동할 수 있는 링크를 생성하였습니다.
현재 페이지와 같을 경우에는 active클래스를 적용하여 강조 표시도 해주었습니다.
{% if page_number >= question_list.number|add:-5 and page_number <= question_list.number|add:5 %}
위 코드는 페이지 리스트가 현재 페이지 기준으로 좌우 5개씩 보이도록 만드는 것입니다.
현재 페이지를 의미하는 question_list.number 보다 5만큼 크거나 작은 값만 표시되도록 만든 것입니다.
즉 위 아래로 5개의 페이지만 노출되는 것입니다.
예를 들어, 현재 페이지가 6이라면 아래 사진과 같이 1~11까지 표시될 것입니다.
본 글은 점프투장고 위키독스를 보고 공부하고 정리한 내용입니다. 자세한 사항은 점프투장고를 참고해 주세요.!^^
'IT > Linux' 카테고리의 다른 글
[Python] django 게시판 게시물의 답변 개수 표시 (0) | 2022.10.13 |
---|---|
[Python] django 게시판 게시글 번호 처리하기 - 템플릿 필터 (0) | 2022.10.12 |
[Python] django include 기능 (2) | 2022.10.07 |
Linux 리눅스 오래된 파일 삭제하기 (0) | 2022.04.13 |
[Linux] 리눅스 CPU 사용률 확인하는 방법 - TOP 명령어 (0) | 2020.11.12 |
댓글