장고:페이징(페이지나누기)

학교의 모든 지식. SMwiki
Sam (토론 | 기여)님의 2020년 11월 3일 (화) 20:34 판 (→‎제네릭 뷰를 사용하는 경우)
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)
둘러보기로 이동 검색으로 이동

장고! 웹 프레임워크! 틀:장고

  1. 장고:개요
  2. 장고:웹페이지설계
    1. 장고:앱
    2. 장고:url
    3. 장고:model
      1. 장고:DB
      2. 장고:모델 필드
      3. 장고:모델의 변경
    4. 장고:view
      1. 장고:클래스형 뷰, 제네릭 뷰
      2. 장고:view 각종 기능
    5. 장고:template
    6. 장고:static. 정적파일 사용하기
      1. 장고:CSS 사용하기
      2. 장고:JS 사용하기
      3. 장고:글꼴 사용
      4. 장고:부트스트랩
    7. 장고:media. 미디어 파일 사용하기
  3. 장고:관리자페이지
  4. 장고:settings.py
  5. 장고:기능구현
    1. 장고:회원관리
    2. 장고:유저
    3. 장고:커스텀 유저
    4. 장고:소셜로그인
    5. 장고:입력받기
    6. 장고:저장된 내용 활용하기
    7. 장고:변수 내보내기
    8. 장고:글쓰기
    9. 장고:페이징(페이지나누기)
    10. 장고:답변쓰기(댓글쓰기)
    11. 장고:추천,즐겨찾기
    12. 장고:새글(최신글) 나타내기
    13. 장고:썸머노트 설치
    14. 장고:네비게이션 바 만들기
    15. 장고:검색기능
    16. 장고:카테고리 만들기
    17. 장고:사진 올리기
    18. 장고:파일 업로드
    19. 장고:이메일app 만들기
    20. 장고:매직 그리드
  6. 장고:웹서비스
    1. 장고:Git
    2. 장고:리눅스에 올리기
    3. 장고:우분투에 올리기(nginx 사용)
    4. 장고:도커로 올리기
  7. 장고:팁

개요[편집 | 원본 편집]

글쓰기에서 작성된 글 리스트를 만들 수 있었다. 일반적인 게시판에선 10, 20개 단위로 글들을 페이징 처리해 두는데, 이 기능이 쉽진 않아 글쓰기와 다른 목차로 떨어뜨려 작성한다.


방법[편집 | 원본 편집]

view 편집[편집 | 원본 편집]

글 목록을 보여주는 view를 다음과 같은 형태로 편집한다.

from django.core.paginator import Paginator #장고엔 다 있다!!

def list(request):
    question_list = Question.objects.order_by('-create_date')

    ################## 페이징처리#########
    page = request.GET.get('page', '1')  #어떤 페이지를 보고 있을지 전달받는다. 전달되는게 없으면 기본적으로 1을받는다는 의미. 추후 탬플릿에서 구현.
    paginator = Paginator(question_list, 10)  # 페이지당 10개씩 보여주겠다는 의미.
    question_list = paginator.get_page(page) #page에 담긴 페이지에 해당하는 리스트를 담는다.

    context = {'question_list': question_list} #기존의 리스트 대신 페이지객체를 보낸다.
    # ---------------------------------------------------------------------------------------- #
    return render(request, 'list.html', context)

paginator의 속성을 page_obj(question_list)에 담아 보냈는데, paginator엔 몇몇 속성이 있다.

쓸만한 paginator 속성
속성 설명
paginator.per_page 페이지당 보여줄 건수
number 현재페이지 번호
num_pages 전체 페이지 갯수
paginator.page_range 페이지 범위. range(시작페이지, 끝페이지) 형태로 얻어진다.
has_previous 이전페이지 존재여부
previous_page_number 이전페이지 번호
has_next 다음페이지 존재여부
next_page_number 다음페이지 번호

이외에도 좀 많다; 자세한 것은 공식 튜토리얼 참조 https://docs.djangoproject.com/ko/3.0/topics/pagination/

제네릭 뷰를 사용하는 경우[편집 | 원본 편집]

제네릭 뷰를 사용하는 경우엔 ListView 안에 paginate_by = 숫자 를 추가한다. 제네릭뷰에선 탬플릿에 page_obj 라는 이름으로 전달된다.

class list(ListView):
    model = Question
    paginate_by=5 #한 페이지에 5개를 보여주겠다는 의미

변수 이름만 통일하면 일반 view의 탬플릿을 그대로 쓸 수 있다.

template 편집[편집 | 원본 편집]

기본적으로 최근 10개의 글만 볼 수 있게 되었다. 다음 글들을 보기 위해선 view에 page 인자를 전달해야 하는데, 이 전달을 위한 페이지 번호매기기가 필요하다.

역시나, 부트스트랩을 이용하면 간결하면서 이쁘게 만들 수 있다.

과정 template
전체 틀 div 안에 페이징처리에 들어갈 요소들을 담으면 편하다.
<ui class="pagination">
...내용은 여기에
</ui>
이전페이지 버튼 만들기 앞번호와 처음링크. 위의 예시를 따른다면 page_obj 대신 question_list를 사용해야 한다. 이름 틀리지 않게 유의.
{% if page_obj.has_previous %}
    <a href="?page=1">처음으로</a>
    <a href="?page={{ page_obj.previous_page_number }}">이전</a>
{% endif %}
이건 앞번호와 처음으로가는 링크만 만들어주는데, 취향에 따라 번호를 매겨줄 수도 있다.

이후 html이나 부트스트랩 따위를 이용해 내용을 꾸며주면 된다.

<li class="page-item"> 따위로.

페이지리스트 만들기 현재 페이지는 구분이 되게 표시를 해준다.
<span class="current">
    Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
이후 html이나 부트스트랩 따위를 이용해 내용을 꾸며주면 된다.
다음페이지 버튼 만들기 다음번호와 끝링크. 위에서와 동일하다.
{% if page_obj.has_next %}
    <a href="?page={{ page_obj.next_page_number }}">다음</a>
    <a href="?page={{ page_obj.paginator.num_pages }}">끝으로</a>
{% endif %}
이건 앞번호와 처음으로가는 링크만 만들어준다.

이후 html이나 부트스트랩 따위를 이용해 내용을 꾸며주면 된다.

얖옆으로 일정 개수의 페이지를 나타내고 싶은 경우[편집 | 원본 편집]

현재 페이지번호보다 5 작고, 5 큰 페이지까지 이동링크를 만들고 싶은 경우. 굉장히 다양한 방법이 있지만, 파이썬을 적극 활용해보자.

view에서 현재페이지를 얻은 후 앞뒤로 숫자 list를 만들어 template로 보낸다. 탬플릿의 '페이지리스트만들기'를 수정한다.

view에서 다음과 같이 보여줄 페이지를 정해 탬플릿으로 보낸다.

current_page_num=int(page)#현재 페이지는 몇인가?
first_page=1#첫 페이지 넘버
last_page=int(paginator.num_pages) #마지막페이지는 몇인가?
left_show =current_page_num - 5 #왼쪽으로 5개까지 나타낸다.
right_show =current_page_num + 5#우측으로 5개까지 나타낸다.

if current_page_num < 6:
    left_show=first_page
if current_page_num+5 > last_page:
    right_show = last_page

page_list = range(left_show, right_show+1)  # 보여줄 페이지의 범위.

context = {'question_list': question_list,#기존의 리스트 대신 페이지객체를 보낸다.
           'page_list':page_list} #보여줄 페이지 리스트

탬플릿은 다음과 같이 고친다.

{% for page_number in page_list %}
    {% if page_number == question_list.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 %}