Django 페이징 #11
참고
https://wikidocs.net/71240
https://wangin9.tistory.com/entry/django-paginator-limit
한 페이지에 모든 글들을 보여준다면 스크롤을 계속 내려서 글을 찾아야합니다. 그러다 글을 보고 다시 리스트 페이지로 돌아온다면 다음글을 보기위해서 또 스크롤을 내려야하는 문제점이 발생합니다. 이외에도 많은 문제들이 생길수 있는데 페이징을 적용하여 해결해 볼 것입니다.
페이지에 10개의 게시물씩 보여줄려면 데이터 베이스에서 10개씩 가져와 보여주면 됩니다.
모두 가져온뒤 1페이지에서는 10번째 글까지 2페이지는 11~20번째 글까지 가져오면됩니다.
이런 기능들을 django에서는 모듈로 간단히 구현할 수 있습니다.
순서
테스트데이터셋 만들기->views.py에 def post_list(post 목록을 받아와 보여주는 함수)에 paginator모듈을 사용하여 paging 처리하기->post_list.html(templates)를 수정하여 paging 적용하기->페이지 리스트도 10개로 제한하기 위해 post_list.html 추가수정->css 추가하기
페이징 테스트를 위한 테스트셋을 만들기(https://developmentdiary.tistory.com/571?category=792571 참조)
이전에 배웠던 Django ORM을 이용하여 반복문을 통해 300개 정도 만들어 놓읍시다.
로 들어갑니다.
-장고인 인터랙티브 콘솔(treminal창에 입력)
1 | python manage.py shell | cs |
1 2 3 4 5 6 7 | from blog.models import Post from django.contrib.auth.models import User me = User.objects.get(username='username') for i in range(300): Post.objects.create(author=me, title='Test'+str(i), text='test'+str(i)) | cs |
paginator 모듈을 사용하여 페이징을 구현합니다.
blog/views.py 수정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger def post_list(request): #페이지 받아오기 page=request.GET.get('page','1')#page의 값을 get방식으로 가져오는데 없을시 디폴트를 '1'로 지정한다. #조회 #posts = Post.objects.order_by('-created_date') posts = Post.objects.all() #페이징처리 paginator=Paginator(posts, 10) try: posts = paginator.page(page) except PageNotAnInteger:#페이지 번호가 없을시 posts = paginator.page(1)#첫번째페이지 보여줌 except EmptyPage:#페이지가 비어있을시(페이지 번호 초과시) posts = paginator.page(paginator.num_pages)#마지막페이지 보여줌 #해당 페이지를 index index = posts.number #마지막 페이지 max_index = len(paginator.page_range) #하단에 보여줄 페이지 범위크기 page_size=5 #해당 페이지에서 앞으로 두칸 page_size보다 작으면 1 start_index = index - page_size if index > page_size else 1 #해당 페이지에서 뒤로 두칸 if index + page_size == max_index:#총 페이지가 3칸 이하일때 end_index=max_index else:#현재 페이지+pase_size가 Max보다 크면 Max로 설정 end_index = index + page_size if index <= max_index else max_index #범위 생성 # 1' Max # 1 Max' # 1' 2 3 ... Max # 1 2' 3 4 ... Max # 1 2 3' 4 5 ... Max # 1 ... 2 3 4' 5 6 ... Max # 1 ... Max-2 Max-1 Max' # 1 ... Max-3 Max-2 Max-1' Max #리스트는 0부터 시작함 page_range = list(paginator.page_range[start_index-1:end_index]) return render(request, 'blog/post_list.html', {'posts': posts, "page_range":page_range, 'max_index': max_index,'page_size':page_size}) | cs |
간단한 페이징 처리는 18번째 줄에서 끝낼수 있지만 그렇게 처리할시 페이지가 많아지면 모든 페이지가 하단에 표시되기 때문에 보기 안좋습니다. 하단에 표시되는 페이지를 제한하기 위해
조금 더 추가하였습니다. 주석으로 설명을 달아놓았습니다.
pase_size를 조절하면 하단에 표시되는 페이지 개수를 바꿀수 있습니다.
Paginator(posts,10)에서 2번째 인자인 10을 조절하면 한페이지에 보여질 리스트 개수를 조절할수 있습니다.
이제 html을 수정하여 봅시다.
blog/templates/blog/post_list.html수정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | {% extends 'blog/base.html' %} {% block content %} {% for post in posts %} <div class="post"> <div class="date"> {{ post.published_date }} </div> <h1><a class="page-link" href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h1> <!--<p>{{ post.text|linebreaksbr }}</p>--> </div> {% endfor %} <ul class="paging"> <!-- 이전페이지 --> {% if posts.has_previous %} <li class="page-item"> <a class="page-link" href="?page={{ posts.previous_page_number }}"> << </a> </li> {% endif %} <!--이전페이지가 충분하지 않은경우--> {% if posts.number > page_size|add:"1" %} <li class="page-item"><a class="page-link" href="?page=1">1</a></li> <li class="page-item"><span class="page-link" >...</span></li> {% endif %} <!-- 페이지리스트 --> {% for page_number in page_range %} {% if page_number == posts.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 posts.number|add:page_size < max_index %} <li class="page-item"><span class="page-link" >...</span></li> <li class="page-item"><a class="page-link" href="?page={{ max_index }}">{{ max_index }}</a></li> {% endif %} {% if posts.has_next %} <li class="page-item"> <a class="page-link" href="?page={{ posts.next_page_number }}"> >> </a> </li> {% endif %} </ul> {% endblock %} | cs |
받아온 인자들을 잘 이용하여 ... 와 >> 표시가 나올지 말지 결정할수 있습니다.
끝값들을 처리하기 위해 max_index와 pase_size를 받아왔습니다.
이제 내용은 생략하고 제목과 작성일만 받아옵니다.
마지막으로 css를 처리해 봅시다.
blog/static/css/style.css수정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /*paging*/ .paging{ justify-content:center;/*센터로 */ display: flex;/*행정렬*/ list-style: none;/* 리스트의 .을 제거합니다.*/ } .paging li a{ color:#111111;/*a 링크 글자는 흰색으로 설정되어 있어서 잘보이게 설정*/ padding:10px 10px;/*간격*/ } .paging li a:hover{/*마우스가 닿으면*/ background-color: orange;/*배경바꾸기*/ border-radius: 4px;/*조금 둥글게*/ } .page-item.active .page-link {/*현재 페이지 표시*/ color: #0000ff;/*현재페이지 파랑색으로 표시*/ } /*end paging*/ | cs |
css처리도 특별한 내용은 없습니다.
글이나 페이징 부분은 아직 모바일에서 봤을때 부족합니다.
디자인을 조금 고민해볼 필요가 있을거 같습니다.
다음엔 로그인 부분을 추가해볼 예정입니다.
github
https://github.com/shjune93/strawberryFarms