📄 Chapter 06. 댓글 페이지네이션 구현하기 (ListView + Bootstrap)
🎯 목표
블로그 상세 페이지에서 댓글이 너무 많아지면 가독성이 떨어지므로, 댓글에 페이지네이션을 적용합니다. 이를 통해 UX를 개선하고, 서버 부하도 줄입니다.
1️⃣ 테스트용 댓글 더미 생성 (shell_plus)
python manage.py shell_plus
comment_list = Comment.objects.filter(blog_id=1)
new_list = []
for i in range(20):
for comment in comment_list:
comment.id = None
new_list.append(comment)
Comment.objects.bulk_create(new_list)
exit
📌 하나의 블로그 글에 많은 댓글을 복제하여 페이지네이션 테스트 준비 완료
2️⃣ BlogDetailView를 ListView로 변경 (cb_views.py)
class BlogDetailView(ListView):
model = Comment
template_name = 'blog_detail.html'
paginate_by = 10
def get(self, request, *args, **kwargs):
self.object = get_object_or_404(Blog, pk=kwargs.get('blog_pk'))
return super().get(request, *args, **kwargs)
def get_queryset(self):
return Comment.objects.filter(blog=self.object).prefetch_related('author')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comment_form'] = CommentForm()
context['blog'] = self.object
return context
✅ 댓글이 페이징된 리스트로 전달됨 (object_list)
✅ 블로그 정보는 self.object로 유지
3️⃣ Blog 모델의 get_absolute_url 수정
class Blog(TimestampModel):
...
def get_absolute_url(self):
return reverse('blog:detail', kwargs={'blog_pk': self.pk})
4️⃣ pagination.html 템플릿 추가
- 공통 페이지네이션 UI 컴포넌트로 사용
- fragment를 이용해 댓글 영역으로 스크롤 이동도 가능
<div class="d-flex justify-content-center">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1{% if fragment %}#{{ fragment }}{% endif %}">« 첫번째</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if fragment %}#{{ fragment }}{% endif %}">이전</a>
</li>
{% endif %}
{% for i in page_obj.paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item"><a class="page-link active" href="#">{{ i }}</a></li>
{% elif i > page_obj.number|add:-3 and i < page_obj.number|add:3 %}
<li class="page-item"><a class="page-link" href="?page={{ i }}{% if fragment %}#{{ fragment }}{% endif %}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if fragment %}#{{ fragment }}{% endif %}">다음</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if fragment %}#{{ fragment }}{% endif %}">마지막 »</a>
</li>
{% endif %}
</ul>
</div>
5️⃣ blog_detail.html에 페이지네이션 적용
{% if request.user.is_authenticated %}
<form method="post" action="{% url 'blog:comment_create' blog.pk %}">
{% csrf_token %}
{{ comment_form.as_p }}
<div class="text-end">
<button class="btn btn-primary">작성</button>
</div>
</form>
{% endif %}
<div class="mb-2" id="comment_wrapper">
{% for comment in object_list %}
<div class="border-bottom">
{{ comment.content }}
<p class="text-end">
<small>{{ comment.created_at|date:'Y-m-d H:i' }} | {{ comment.author.username }}</small>
</p>
</div>
{% endfor %}
</div>
{% include 'pagination.html' with fragment='comment_wrapper' %}
6️⃣ URL 패턴 변경 (urls.py)
path('<int:blog_pk>/', cb_views.BlogDetailView.as_view(), name='detail'),
✅ 최종 요약
- 댓글을 ListView 기반으로 페이지네이션 처리
- fragment를 이용해 페이지 이동 후 댓글 영역으로 자동 스크롤 이동
- 템플릿 모듈화(pagination.html)로 재사용성 향상
👉 실무에서는 Ajax로 댓글만 비동기 로딩하거나, 무한스크롤로 확장할 수 있습니다!
'Django' 카테고리의 다른 글
Chapter 7-2 Django 블로그 글 작성/수정 폼에 Summernote 적용하기 (0) | 2025.05.11 |
---|---|
Chapter 7-1 Django 블로그 이미지 업로드 기능 만들기 (0) | 2025.05.11 |
Chapter 6-4 Django 블로그에 댓글 기능 추가하기 (0) | 2025.05.09 |
Chapter 6-3 댓글 기능 시작하기 - 모델과 관리자 설정 (0) | 2025.05.09 |
Chapter 6-2 Bootstrap 적용으로 블로그 UI 개선하기 (0) | 2025.05.09 |