개발로 자기계발
article thumbnail
728x90

1) 라이브러리

from django.core.paginator import Paginator

 장고 내에 구현된 라이브러리로 불러온 객체를 페이징 객체로 변환시켜 준다.

 

 2) 페이지 옵션 설정

# 장고ORM으로 데이터 쿼리셋 추출
foods = models.Food.objects.filter(name__icontains=food).order_by('name')

데이터 쿼리 셋을 가져왔다고 가정해 보자(filter내 들어가 있는 것은 Like 검색이다)

# 한 페이지에 n개씩 노출
page_count = n

# foods의 쿼리셋을 페이징객체로 변환시키고 n개를 한 페이지에 보여준다.
paginator = Paginator(foods, page_count)
# 현재 웹에서 요청하는 페이지 번호를 가져온다.
# 페이지가 있다면 get('page') 없다면 1이다.
page = request.GET.get('page', 1)
# 페이지 번호 page에 해당하는 Page 객체를 반환한다.
# Page 객체는 해당 페이지의 객체들을 담은 리스트(object_list),
# 전체 페이지 개수(num_pages),
# 현재 페이지 번호(number),
# 이전 페이지 번호(previous_page_number),
# 다음 페이지 번호(next_page_number)등의 속성을 가진다.
paginated_foods = paginator.get_page(page)

※ 추가로 paginated_foods.object_list로 현재 페이지의 음식 객체 리스트를 반환받을 수 있다.

 

3) Views.py 구현해 보기

def search(request):
    food = request.GET.get('food')
    if food:
        # 검색어를 포함하는 음식 데이터 조회
        foods = models.Food.objects.filter(name__icontains=food).order_by('name')
    else:
    	# 검색어가 없다면 전체 리스트 반환
        foods = models.Food.objects.all().order_by('name')

    # 한 페이지에 10개씩
    page_count = 10
    # foods를 페이징객체로 변환
    paginator = Paginator(foods, page_count)
    # 요청받은 페이지 번호 가져오기
    page = request.GET.get('page', 1)
    # 페이지에 해당하는 객체 반환
    paginated_foods = paginator.get_page(page)

    return render(request, "search.html", {"foods": paginated_foods})

음식 검색 기능을 구현한다면 이렇게 만들 수 있을 것이다.

 

4) search.html 구현해 보기

<div>
   <h2 class="headtxt">검색하기</h2>
   <form method="GET">
         <span>
            <input type="text" name="food" placeholder="검색어를 입력해주세요."/>
         </span>
         <button>검색</button>
   </form>
   <div>
      <ul>
         {% for food in foods %}
     		<li>
              <span class="nutri_food_name">{{ food.name }}</span>
            </li>
         {% endfor %}
      </ul>
   </div>
</div>

{# 여기서 부터 페이징 #}
<div>
   {# 이전 페이지 존재한다면 #}
    {% if foods.has_previous %}
        <a href="?page=1&food={{ request.GET.food }}">&laquo; 처음</a>
        <a href="?page={{ foods.previous_page_number }}&food={{ request.GET.food }}">&lt; 이전</a>
    {% endif %}

   {# 요청받는 값 만큼 페이지 수 확인 #}
    {% for num in foods.paginator.page_range %}
    	{# 현재 페이지랑 같다면 강조 #}
        {% if num == foods.number %}
            <strong>{{ num }}</strong>
        {% else %}
        {# 페이지 번호 뿌리기 #}
            <a href="?page={{ num }}&food={{ request.GET.food }}">{{ num }}</a>
        {% endif %}
    {% endfor %}

   {# 다음 페이지 존재한다면 #}
    {% if foods.has_next %}
        <a href="?page={{ foods.next_page_number }}&food={{ request.GET.food }}">다음 &gt;</a>
        <a href="?page={{ foods.paginator.num_pages }}&food={{ request.GET.food }}">마지막 &raquo;</a>
    {% endif %}
</div>

대략 이렇게 구현할 수 있을 것이다.

주의 깊게 봐야 할 곳은 페이징 부분인데, foods는 페이징의 객체를 받았기 때문에 이에 따른 속성 사용이 가능하다.

 

1. 이전 페이지가 존재하게 되면 처음과 이전 버튼이 생긴다.

2. 다음 페이지가 존재하게되면 다음과 마지막 버튼이 생긴다.

3. 객체의 수만큼 페이지 번호를 만들어 준다.

 

이런식으로 구현이 된다.

 

728x90
SMALL
profile

개발로 자기계발

@김잠봉

틀린부분이나 조언이 있다면 언제든 환영입니다:-)