(2024.07.02. 수정됨.)
주요 파일 경로
blog
|- manage.py
|- entry
| |- url.py
| |- views.py
|- templates
|- index.html
|- style.html
게시글 작성과 조회, 수정과 삭제까지 만들었지만 아직 부족한게 있습니다.
게시글 목록을 조회할 때, 게시글 일부가 아닌 작성한 모든 게시글이 목록에 표시되는 것인데요.
이번에는 게시글 목록 페이지를 분리하는 방법을 알아보겠습니다.
게시글 양산하기
페이지를 구현하려면 먼저 다수의 게시글이 있어야 합니다. 장고에서 제공하는 shell 기능으로 다수의 게시글을 만들어봅시다.
shell 실행하기
"python manage.py shell" 명령어로 실행할 수 있습니다.
(python3.10) C:\seolpyo\python3.10\Django\blog>python manage.py shell
모델 import
"from entry.models import Post"를 입력해 모델을 import합니다.
>>> from entry.models import Post
데이터 생성하기
for loop를 이용해 Post object를 생성하고, save해줍니다. 루프 명령어를 입력한 다음 엔터 키를 입력하면 "..."이 표시되는데, 아무것도 입력하지 않고 다시 한 번 엔터 키를 입력하면 됩니다.
>>> for i in range(30): Post(title=f'test post {i}', content=f'test content {i}').save()
...
저장된 데이터 호출하기
Post.objects.all() 명령으로 전체 데이터를 호출할 수 있습니다.
>>> Post.objects.all()
<QuerySet [<Post: Post object (5)>, <Post: Post object (6)>, <Post: Post object (7)>, <Post: Post object (8)>, <Post: Post object (9)>, <Post: Post object (10)>, <Post: Post object (11)>, <Post: Post object (12)>, <Post: Post object (13)>, <Post: Post object (14)>, <Post: Post object (15)>, <Post: Post object (16)>, <Post: Post object (17)>, <Post: Post object (18)>, <Post: Post object (19)>, <Post: Post object (20)>, <Post: Post object (21)>, <Post: Post object (22)>, <Post: Post object (23)>, <Post: Post object (24)>, '...(remaining elements truncated)...']>
또는 count method로 저장된 데이터의 개수를 가져올 수도 있습니다.
데이터가 만들어졌는지 확인만 하면 되니 이쪽이 더 간단합니다.
>>> Post.objects.all().count()
33
shell 종료하기
"Ctrl" + "z" 입력 후 엔터를 입력하면 python shell을 종료할 수 있습니다.
>>> ^Z
전체 과정
전체 과정을 따라했다면 cmd에 다음과 같은 텍스트가 남아있을 겁니다.
(python3.10) C:\seolpyo\python3.10\Django\blog>python manage.py shell
Python 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from entry.models import Post
>>> for i in range(30): Post(title=f'test post {i}', content=f'test content {i}').save()
...
>>> Post.objects.all()
<QuerySet [<Post: Post object (5)>, <Post: Post object (6)>, <Post: Post object (7)>, <Post: Post object (8)>, <Post: Post object (9)>, <Post: Post object (10)>, <Post: Post object (11)>, <Post: Post object (12)>, <Post: Post object (13)>, <Post: Post object (14)>, <Post: Post object (15)>, <Post: Post object (16)>, <Post: Post object (17)>, <Post: Post object (18)>, <Post: Post object (19)>, <Post: Post object (20)>, <Post: Post object (21)>, <Post: Post object (22)>, <Post: Post object (23)>, <Post: Post object (24)>, '...(remaining elements truncated)...']>
>>> Post.objects.all().count()
33
>>> ^Z
now exiting InteractiveConsole...
(python3.10) C:\seolpyo\python3.10\Django\blog>
페이징 구현하기
이제 페이지를 구분할 정도의 게시글이 만들어졌으니, 페이지마다 8개의 게시글을 노출하도록 해보겠습니다.
view 수정하기
글 목록 페이지 구현에는 Paginator가 사용됩니다.
또한 현재 몇 번째 페이지를 조회하는지에 대한 값도 받아야 하기 때문에 index 함수를 다음과 같이 수정합니다.
# entry/views.py
...
from django.core.paginator import Paginator # 추가
...
# 수정하기
def index(request: HttpRequest, page: int=1):
context = {}
paginator = Paginator(Post.objects.all(), 8)
page_obj = paginator.get_page(page)
context.update({
'title': '글 목록',
'paginator': paginator,
'page_obj': page_obj,
'object_list': page_obj.object_list,
})
return render(request, 'index.html', context)
...
url 추가하기
page라는 이름의 url을 추가합니다.
# entry/urls.py
from django.urls import path
from . import views
app_name = 'entry'
urlpatterns = [
path('', views.index, name='index'),
path('page/<int:page>/', views.index, name='page'), # 추가
...
]
템플릿 수정하기
템플릿을 수정해 페이지 조회시 현재 페이지를 표시하고, 페이지의 처음과 끝, 이전 페이지와 다음 페이지 이동 링크를 추가합니다.
# templates/index.html
{% extends 'base.html' %}
{% block title %}{{ title }}{% endblock %}
{% block main %}
<div>
<a href="{% url 'entry:post' %}">글 작성하기</a>
</div>
<hr>
<article>
{% for object in object_list %}
<p><a href="{{ object.get_absolute_url }}">{{ object.title }}</a></p>
{% empty %}
<p>작성된 글이 없습니다.</p>
{% endfor %}
</article>
<div class="page">
<ul>
{% if page_obj.has_previous %}
<li>
<a href="{% url 'entry:index' %}">처음</a>
</li>
<li>
<a href="{% url 'entry:page' page_obj.previous_page_number %}">이전</a>
</li>
{% endif %}
<li>
<b>{{ page_obj.number }}</b>
</li>
{% if page_obj.has_next %}
<li>
<a href="{% url 'entry:page' page_obj.next_page_number %}">다음</a>
</li>
<li>
<a href="{% url 'entry:page' paginator.num_pages %}">끝</a>
</li>
{% endif %}
</ul>
</div>
{{ page_obj.page }}
{% endblock %}
css 수정하기
ul과 li 태그를 사용했기 때문에 페이지가 세로로 정렬됩니다.
가로로 표시될 수 있도록 style.html을 수정해줍니다.
# templates/style.html
<style>
...
div.page ul {
display: flex;
place-content: center;
}
div.page li {
display: block;
margin: 10px;
}
...
</style>
확인해보기
이제 글 목록에 페이지가 적용됩니다.

이 글의 댓글 기능은 일부러 막아놓았습니다. 궁금한 내용이 있다면 게시판을 이용해주세요!