Django

16. 게시판 페이징 기능 구현하기

테니드2 2021. 4. 15. 11:30

- 게시판 임시 데이터 만들기

 

#파이썬 쉘 진입 및 라이브러리 추가

>python manage.py shell
# 파이썬 쉘 진입
>>> from pybo.models import Question
>>> from django.utils import timezone  

 

#반복문을 이용하여 데이터 삽입

>>> for i in range(300):
...    q = Question(subject='테스트 데이터:[%03d]' % i, content='컨텐츠 내용', create_date=timezone.now())
...    q.save() 
...    
>>>

 

# ListView를 이용한 간단한 페이징 구현 (project/main/views.py)

class index(ListView):
    model = Question
    # 템플릿 파일 지정
    template_name = 'main/index.html'
    # 화면에 표시될 데이터의 개수
    paginate_by = 10

	# 추가로 보낼 데이터
    def get_context_data(self, **kwargs):
        context = super(index, self).get_context_data()
        context['page_title'] = '질문과 답변'
        return context
	# request를 받으면 실행되는 Query
    def get_queryset(self):
        return self.model.objects.order_by('-create_date')

❖ paginate_by = 한 페이지에 보여질 데이터 개수 로 값을 설정하면 한 페이지에 대한 데이터들은 기본적으로 page_obj라는 변수에 들어가게 된다.

 

# 템플릿 구현 (project/main/templates/index.html)

{% extends 'base.html' %}
{% load custom_filter %}
{% block page_title %} {{ page_title }} {% endblock %}
{% block content %}
    <div class="container my=3">
    <table class="table">
        <thead>
        <tr class="thead-dark">
            <th>번호</th>
            <th>제목</th>
            <th>작성일시</th>
        </tr>
        </thead>
        <tbody>
        {% if page_obj %}
            {% for question in page_obj %}
                <tr>
                    <td>{{ paginator.count }}</td>
                    <td>
                        <a href="{% url 'main:detail' question.id %}">{{ question.subject }}</a>
                        {% if question.answer_set.count > 0 %}
                            <span class="text-danger small ml-2">{{ question.answer_set.count }} </span>
                        {% endif %}
                    </td>
                    <td>{{ question.create_date }}</td>
                </tr>
            {% endfor %}
        {% else  %}
            <tr>
                <td colspan="3">질문이 없습니다.</td>
            </tr>
        {% endif %}
        </tbody>
    </table>
    <!-- page nav -->
    <ul class="pagination justify-content-center">
       <!-- 이전 페이지-->
        {% if page_obj.has_previous %}
        <li class="page-item">
            <a class="page-link" href="?page={{ page_obj.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 paginator.page_range %}
        {% if page_number == page_obj.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 page_obj.has_next %}
        <li class="page-item">
            <a class="page-link" href="?page={{ page_obj.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 'main:question_create' %}" class="btn btn-primary">질문 등록</a>
    </div>
{% endblock %} #}

 

 

- 결과 화면

 

☑︎ 문제점

• 1. 각 페이지 번호가 1~10로 고정 되어 있는 점

• 2. 페이지 번호가 너무 많아져 정상적으로 표기가 안되는 점

 

# 사용자 지정 템플릿 필터 만들기 (sub: 빼기 연산을 위한 필터)

1. 템플릿 필터 폴더 만들기: 템플릿 폴더와 같은 위치에 templatetags 폴더 생성

2. filter.py 생성

from django import template

register = template.Library()


@register.filter
def sub(value, arg):
    return value - arg

 

3. 적용할 템플릿 상단에 {% load 'filter 파일명' %} 작성

 

{% extends 'base.html' %}
{% load custom_filter %}
{% block page_title %} {{ page_title }} {% endblock %}
{% block content %}
    <div class="container my=3">
    <table class="table">
        <thead>
        <tr class="thead-dark">
            <th>번호</th>
            <th>제목</th>
            <th>작성일시</th>
        </tr>
        </thead>
        <tbody>
        {% if page_obj %}
            {% for question in page_obj %}
                <tr>
                	<!-- 1. 문제점 해결책 각 페이지 번호 -->
                    <!-- 번호 = 전체 건수 - 시작인덱스 - 현재인덱스 +1 -->
                    <td>{{ paginator.count | sub:page_obj.start_index|sub:forloop.counter0|add:1 }}</td>
                    <td>
                        <a href="{% url 'main:detail' question.id %}">{{ question.subject }}</a>
                        {% if question.answer_set.count > 0 %}
                            <span class="text-danger small ml-2">{{ question.answer_set.count }} </span>
                        {% endif %}
                    </td>
                    <td>{{ question.create_date }}</td>
                </tr>
            {% endfor %}
        {% else  %}
            <tr>
                <td colspan="3">질문이 없습니다.</td>
            </tr>
        {% endif %}
        </tbody>
    </table>
    <!-- page nav -->
    <ul class="pagination justify-content-center">
       <!-- 이전 페이지-->
        {% if page_obj.has_previous %}
        <li class="page-item">
            <a class="page-link" href="?page={{ page_obj.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 paginator.page_range %}
        <!-- 2. 문제점 해결 페이지 버튼 수 조정 -->
        <!-- 페이지 수 조정 -->
        {% if page_number >= page_obj.number|add:-5 and page_number <= page_obj.number|add:5 %}
            {% if page_number == page_obj.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 %}
        {% endif %}
        {% endfor %}
        <!-- 다음 페이지 -->
        {% if page_obj.has_next %}
        <li class="page-item">
            <a class="page-link" href="?page={{ page_obj.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 'main:question_create' %}" class="btn btn-primary">질문 등록</a>
    </div>
{% endblock %} #}

 

- 결과 화면

 

 

 

출처: wikidocs.net/book/4223 (점프 투 장고)