Pagenator객체.page(페이지 번호)Page객체.has_previous() / Page객체.has_next()먼저 기존 list 함수를 list_no_paging으로 변경한다.
# views.py
def list_no_paging(request): # 함수 이름 변경: list -> list_no_paging
# DB에서 question들을 조회
q_list = Question.objects.all().order_by("-pub_date") # 내림차순 -> 최신 질문 목록
# render(): template을 실행해서 그 결과로 HttpResponse를 반환하는 함수.
return render(
request, # HttpRequest 객체
"polls/list.html", # Template 파일의 경로
{"question_list": q_list} # Template에게 전달할 값 -> context value: dictionary
)
# views.py
from django.core.paginator import Paginator
###########################
# list -> paging 처리 목록 View
# - 요청파라미터(querystring)으로 page 번호를 받는다. (=get 방식)
# - 응답 context value(data)
# - 현재 page에 보여줄 데이터들
# - 현재 페이지가 속한 페이지 그룹의 시작/끝 페이지 번호
# - 현재 페이지 그룹의 시작 페이지가 **이전페이지가 있는지 여부/이전 페이지 번호**
# - 현재 페이지 그룹의 끝 페이지가 **다음페이지가 있는지 여부/다음 페이지 번호**
def list(request):
pagenate_by = 10 # 한 페이지당 데이터 개수
page_group_count = 10 # 한 페이지 그룹당 페이지 수
# http://ip:port/polls/list?page=15 -> 15를 받아서 int로 바꿈
# http://ip:port/polls/list -> 받은 번호가 없다면 기본값 1을 반환
current_page = int(request.GET.get('page', 1)) # 현재 조회하려는 페이지 번호, default=1
# 기본적으로 문자열 형태로 반환 -> int로 변환.
# Question 데이터 조회 + Pagenator 객체 생성
question_list = Question.objects.all().order_by("-pk")
pn = Paginator(question_list, pagenate_by)
# 현재 페이지가 속한 페이지 그룹의 start/end 페이지 번호 조회
start_index = int((current_page-1)/page_group_count) * page_group_count
end_index = start_index + page_group_count
page_range = pn.page_range[start_index:end_index]
# context_value(context_data) -> template에 전달할 값들. dictionary
context_value = {
"page_range": page_range, # Page group의 시작/끝페이지 range
"question_list": pn.page(current_page) # 페이지의 데이터들
}
# 페이지 그룹의 시작 페이지가 이전 페이지가 있는지, 이전 페이지 번호는 무엇인지
start_page = pn.page(page_range[0])
has_previous = start_page.has_previous()
if has_previous:
previous_page = start_page.previous_page_number()
context_value['has_previous'] = has_previous
context_value['previous_page'] = previous_page
# 페이지 그룹의 끝 페이지가 다음 페이지가 있는지, 다음 페이지 번호는 무엇인지
end_page = pn.page(page_range[-1])
has_next = end_page.has_next()
if has_next:
next_page = end_page.next_page_number()
context_value['has_next'] = has_next
context_value['next_page'] = next_page
return render(request, "polls/list.html", context_value)
<!-- polls/templates/polls/list.html -->
{%extends "layouts/main_layout.html"%}
{%block title%}설문 목록{%endblock title%}
{%block contents%}
<h1>설문 목록</h1>
<div class="list-group"> <!-- ⭐ div 그룹으로 묶어줌 -->
{% for question in question_list %} <!-- for문 시작 -->
<!-- <a href="/polls/vote_form/{{question.pk}}"> -->
<!-- ⭐ a 태그에 클래스 추가 -->
<a href="{% url 'polls:vote_form' question.pk %}" class="list-group-item list-group-item-action">
{{question.pk}}. {{question.question_text|truncatewords:4}}<br>
</a>
{% empty %}
<b>등록된 설문이 없습니다.</b>
{% endfor %} <!-- for문 끝 -->
</div>
{%endblock contents%}

질문 항목 위에 마우스를 대면 색이 변한다. (class - action)
<!-- polls/templates/polls/list.html -->
{%extends "layouts/main_layout.html"%}
{%block title%}설문 목록{%endblock title%}
{%block contents%}
<h1>설문 목록</h1>
<div class="list-group">
{% for question in question_list %} <!-- for문 시작 -->
<!-- <a href="/polls/vote_form/{{question.pk}}"> -->
<a href="{% url 'polls:vote_form' question.pk %}" class="list-group-item list-group-item-action">
{{question.pk}}. {{question.question_text|truncatewords:4}}<br>
</a>
{% empty %}
<b>등록된 설문이 없습니다.</b>
{% endfor %} <!-- for문 끝 -->
</div>
<!-- paging 처리 -> 이동할 페이지 링크 추가 -->
<ul>
{# 이전 페이지 그룹 이동 버튼 #}
{% if has_previous %}
<li>
<a href="{% url 'polls:list' %}?page={{previous_page}}">
이전
</a>
</li>
{% else %}
<li>
<span>⬅️ 이전</span>
</li>
{% endif %}
{# 이동할 페이지 번호, 링크 #}
{# 다음 페이지 그룹 이동 버튼 #}
{% if has_next %}
<li>
<a href="{% url 'polls:list' %}?page={{next_page}}">
다음
</a>
</li>
{% else %}
<li>
<span>다음 ➡️</span>
</li>
{% endif %}
</ul>
{%endblock contents%}

넘어갈 페이지가 있으면 a 태그, 없으면 스판 태그(화살표 있는 거)가 뜬다.
<!-- polls/templates/polls/list.html -->
{%extends "layouts/main_layout.html"%}
{%block title%}설문 목록{%endblock title%}
{%block contents%}
<h1>설문 목록</h1>
<div class="list-group">
{% for question in question_list %} <!-- for문 시작 -->
<!-- <a href="/polls/vote_form/{{question.pk}}"> -->
<a href="{% url 'polls:vote_form' question.pk %}" class="list-group-item list-group-item-action">
{{question.pk}}. {{question.question_text|truncatewords:4}}<br>
</a>
{% empty %}
<b>등록된 설문이 없습니다.</b>
{% endfor %} <!-- for문 끝 -->
</div>
<!-- paging 처리 -> 이동할 페이지 링크 추가 -->
<ul class="pagination mt-3">
{# 이전 페이지 그룹 이동 버튼 #}
{% if has_previous %}
<li class="page-item">
<a href="{% url 'polls:list' %}?page={{previous_page}}" class="page-link">
이전
</a>
</li>
{% else %}
<li class="page-item">
<span class="page-link disabled">⬅️ 이전</span>
</li>
{% endif %}
{# 이동할 페이지 번호, 링크 - 현재 페이지는 링크를 걸지 않는다. #}
{% for page_no in page_range %}
{% if page_no == question_list.number %}
<li class="page-item">
<span class="page-link disabled">{{page_no}}</span>
</li>
{% else %}
<li class="page-item">
<a href="{% url 'polls:list' %}?page={{page_no}}" class="page-link">
{{page_no}}
</a>
</li>
{% endif %}
{% endfor %}
{# 다음 페이지 그룹 이동 버튼 #}
{% if has_next %}
<li class="page-item">
<a href="{% url 'polls:list' %}?page={{next_page}}" class="page-link">
다음
</a>
</li>
{% else %}
<li class="page-item">
<span class="page-link disabled">다음 ➡️</span>
</li>
{% endif %}
</ul>
{%endblock contents%}
문제
{{% if page_no == question_list.number %}}
틀린 문법입니다.
💡 Django 템플릿에서 if문은 {% if ... %}로 써야 하고, 중괄호 두 개({{ }})는 변수 출력에만 씁니다.
해결 방법
{% if page_no == question_list.number %}