아래는 티스토리 블로그에서 캡쳐한 사진이다.
이처럼 일반적으로 사용하는 사이트는 이와 같이 데이터를 페이지 별로 나눠 보내는데, 이러한 기능을 Pagination
이라고 한다.
Django 는 모듈을 통해 Pagination
기능을 제공한다.
blog/views.py
# 이전 import문들..
from django.core.paginator import Paginator
def home(request):
blogs = Blog.objects.all() #blog 객체를 모두 가져온다
paginator = Paginator(blogs, 3) # blogs를 3개씩 쪼갠다
page = request.GET.get('page') # 해당 정보가 오지 않아도 넘어간다
paginated_blogs = paginator.get_page(page)
return render(request, 'home.html', {'blogs': paginated_blogs})
paginator = Paginator(blogs, 3)
page = request.GET.get('page')
request.GET['page']
와 다른 메소드를 사용해보자.request.GET['page']
는 request에 'page'가 없다면 MultiValueDictKeyError 를 발생시킨다.request.GET.get('page')
는 request에 'page'가 없다면 None을 리턴한다.paginated_blogs = paginator.get_page(page)
blog/templates/home.html
{% extends 'base.html' %}
{% block content %}
{% if user.is_authenticated %}
{{user.location}}에 사는 {{user.university}} 다니는 {{user.nickname}}님 안녕하세요!
{% endif %}
<h1>Blog Project</h1>
<h4><a href="{% url 'blog:new' %}">New Post</a></h4>
<div class="conatainer">
{% for blog in blogs%}
<div>
<h3>{{ blog.title }}</h3>
{{ blog.id }} <br />
{{ blog.writer }} <br />
{{ blog.summary }}
<a href="{% url 'blog:detail' blog.id %}">...more</a>
</div>
{% endfor %}
</div>
<br/>
<div class="paginator">
{% if blogs.has_previous %}
<a href="?page=1">처음</a>
<a href="?page={{blogs.previous_page_number}}">이전</a>
{% endif %}
<span>{{blogs.number}}</span>
<span>of</span>
<span>{{blogs.paginator.num_pages}}</span>
{% if blogs.has_next %}
<a href="?page={{blogs.next_page_number}}">다음</a>
<a href="?page={{blogs.paginator.num_pages}}">마지막</a>
{% endif %}
</div>
{% endblock %}
코드가 조금 지저분하므로 다음과 같이 <div class="container">와 <div class="paginator">로 나눠주었다.
{% if blogs.has_previous %}
{{blogs.previous_page_number}}
{{blogs.next_page_number}}
{{blogs.paginator.num_pages}}
<a href="?page=1">
order_by()
메소드를 통해 구현할 수 있다.filter()
메소드도 사용해서 검색 기능을 구현할 수도 있다.blog/views.py
def home(request):
query = request.GET.get('query')
search = request.GET.get('search')
if query:
blogs = Blog.objects.filter(title__icontains = query).order_by('-pub_date')
elif search:
author = request.GET.get('user')
user = CustomUser.objects.get(username=author)
blogs = Blog.objects.filter(user = user).order_by('-pub_date')
else:
blogs = Blog.objects.order_by('-pub_date')
paginator = Paginator(blogs, 3)
page = request.GET.get('page')
paginated_blogs = paginator.get_page(page)
return render(request, 'home.html', {"blogs" : paginated_blogs, "search": search})
order_by()
: 정렬해서 데이터 가져옵니다.
filter()
: 조건을 걸어 원하는 데이터만 가져옵니다.
더욱 다양한 쿼리셋 API 알아보기 : https://docs.djangoproject.com/en/3.2/ref/models/querysets/
template 수정하기
blog/templates/home.html
{% extends 'base.html' %} {% block content %}
<body>
{% if user.is_authenticated %} {{user.location}}에 사는
{{user.university}}다니는 {{user.nickname}} 안녕하세요! {% endif %}
<form action="{% url 'home' %}">
<p>제목으로 게시글 검색</p>
<input type="text" name="query" />
<input type="submit" value="Search" />
</form>
<!-- <h1>Blogs : {{blogs}}</h1> -->
<a href="?search=true&user={{user.username}}">내가 쓴 글</a>
<hr />
<a href="{% url 'blog:new_django_form' %}">새 블로그 생성하기!</a>
<hr />
{% for blog in blogs %} 글번호 : {{blog.id}}
<br />
제목 : {{blog.title}}
<br />
작성자 : {{blog.writer}}
<br />
내용 : {{blog.summary}}
<br />
<a href="{% url 'blog:detail' blog.id %}">more..</a>
<br />
<a href="{% url 'blog:update' blog.id %}">update..</a>
<br />
<a href="{% url 'blog:delete' blog.id %}">delete..</a>
<hr />
{% endfor %}
<br />
<div class="paginator">
{% if blogs.has_previous %}
<a href="?page=1">처음</a>
{% if search %}
<a
href="?search=true&user={{user.username}}&page={{blogs.previous_page_number}}"
>이전</a
>{% else %}
<a href="?page={{blogs.previous_page_number}}">이전</a>
{% endif %} {% endif %}
<span>{{blogs.number}}</span>
<span>of</span>
<span>{{blogs.paginator.num_pages}}</span>
{% if search %}
{% if blogs.has_next %}
<a href="?search=true&user={{user.username}}&page={{blogs.next_page_number}}">다음</a>
<a href="?search=true&user={{user.username}}&page={{blogs.paginator.num_pages}}">마지막</a>
{% endif %}
{% else %}
{% if blogs.has_next %}
<a href="?page={{blogs.next_page_number}}">다음</a>
<a href="?page={{blogs.paginator.num_pages}}">마지막</a>
{% endif %}
{% endif %}
</div>
</body>
{% endblock %}