반응형

참고

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

반응형

'웹개발 > Django' 카테고리의 다른 글

Django 소셜로그인 #13  (0) 2020.12.24
Django 로그인/회원가입 #12  (0) 2020.12.20
Django 네비게이션바 #10  (0) 2020.12.14
Django 추가,수정 페이지 만들기 #9  (0) 2020.12.14
Django 다른페이지 추가해보기 #8  (0) 2020.12.13
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기