본문 바로가기
프로젝트/여행석사

여행석사 - Pagination 기능

by JayAlex07 2023. 2. 22.

검색 기능 - Pagination (페이지네이션)

 

Search의 모델

class Search(models.Model):
    # 검색할 때, 받는 필드
    title = models.CharField(max_length=10)
    # 인기 검색어를 위해 필요한 필드
    count = models.PositiveIntegerField(default=0)

 

views.py의 검색 기능

def search(request):
    popular_list = {}
    if request.method == "GET":
        search = request.GET.get("searched", "")
        sort = request.GET.get("sorted", "")

        if not search.isdigit() and not search == "":
            if Review.objects.filter(
                Q(title__icontains=search)
                | Q(content__icontains=search)
                | Q(place__icontains=search)
            ):
                popular_list[search] = popular_list.get(search, 0) + 1

        for k, v in sorted(popular_list.items(), key=lambda x: -x[1]):
            if Search.objects.filter(title=k):
                s = Search.objects.get(title=k)
                s.count += 1
                s.save()
            else:
                s = Search(title=k, count=v)
                s.save()
        popular = Search.objects.order_by("-count")[:10]

        search_list = Review.objects.filter(
            Q(title__icontains=search)
            | Q(content__icontains=search)
            | Q(place__icontains=search)
            | Q(theme__icontains=search)
            | Q(user_id__profile_name__icontains=search)
        )

        if search:
            if search_list:
                pass

            if sort == "pop":
                search_list = search_list.order_by("-like_users")
                sort="pop"
                print(search_list)

            if sort == "recent":
                search_list = search_list.order_by("-updated_at")
                sort="recent"
                print(search_list)

            page = int(request.GET.get("p", 1))
            pagenator = Paginator(search_list, 5)
            boards = pagenator.get_page(page)

            return render(
                request,
                "articles/search.html",
                {
                    "search": search,
                    # 페이별로 저장된 queryset을 가지고 온다
                    "boards": boards,
                    # 검색어에 대한, 검색된 queryset들의 리스트를 가지고 온다
                    "search_list": search_list,
                    # 검색이 많이 된 순으로 queryset을 정리해서 가지고 온다
                    "popular": popular,
                    # 특정 필드로 인해 정렬된 queryset들을 가지고 온다
                    "sort" : sort,
                },
            )
        else:
            k = "검색 결과가 없습니다 다시 검색해주세요"
            context = {"v": k}
            return render(request, "articles/searchfail.html", context)

 

✍️ from django.db.models import Q

- 주로 .filter ORM을 사용할 때, 어떠한 정보를 찾을 때 사용한다
- 주로 | & ^ 를 사용한다 (순서대로, and, or, xor)

- 예시)
        ORM : Q(question__startswith='Who') | Q(question__startswith='What')
        SQL : WHERE question LIKE 'Who%' OR question LIKE 'What%'

 


 

코드 뜯어내기

 

pagination 기능

한 페이지에 너무 많은 데이터가 있을 때에, 페이지를 나누는 것이다.
다음 페이지로 넘어가기 버튼 또는, 페이지 번호로 가는 버튼을 통해서 페이지를 넘어간다.

 

views.py

from django.core.paginator import Paginator

page = int(request.GET.get("p", 1))
pagenator = Paginator(search_list, 5)
boards = pagenator.get_page(page)
  • 장고에는 페이지를 나눌 수 있는 Paginator가 있다
  •  page = int(request.GET.get("p", 1)) 
    • client가 요청한 url에 p, 페이지의 변수를 가지고 온다 (여기서 기본 설정은 1이다)
    • 기본 설정이 1이란 것은, 첫번째 페이지를 끌고 온다는 것이다
  •  pagenator = Paginator(search_list, 5) 
    • search_list는 검색해서 받은 queryset들의 리스트들의 변수 명이다 (search 기능에서 확인 가능)
    • search_list를 한 페이지 당 5개씩 가지고 온다
  •  boards = pagenator.get_page(page) 
    • pagenator에 저장한 queryset들 (여기서 5개)를 가지고 온다
    • pagenator는 각 페이지 당 5개씩 저장이 되어 있고, url에서 불러온 `p`의 값을 `boards`에 저장한다

📌📌📌`page`는 유저가 요청한 몇 번째 페이지 → `pagenator`는 각 페이지 당 몇개의 queryset을 저장할지 지정 → `boards`는 유저가 요청한 페이지의 queryset들을 가지고 온다

 

 

HTML

<div class="row mt-2">
  <div class="col-12 my-5">
    <nav aria-label="Page navigation example">
      <ul class="pagination justify-content-center">
        {% if boards.has_previous %}
          <li class="page-item">
            <a class="page-link" href="?searched={{ search }}&sorted={{ sort }}&p={{ boards.previous_page_number }}">이전</a>
          </li>
        {% else %}
          <li class="page-item disabled">
            <a class="page-link" href="#">이전</a>
          </li>
        {% endif %}
        <li class="page-item">
          <a class="page-link" href="#">{{ boards.number }}
            /
            {{ boards.paginator.num_pages }}</a>
        </li>
        {% if boards.has_next %}
          <li class="page-item">
            <a class="page-link" href="?searched={{ search }}&sorted={{ sort }}&p={{ boards.next_page_number }}">다음</a>
          </li>
        {% else %}
          <li class="page-item disabled">
            <a class="page-link" href="#">다음</a>
          </li>
        {% endif %}
      </ul>
      </nav>
    </div>
  </div>

 href="?searched={{ search }}&sorted={{ sort }}&p={{ boards.previous_page_number }}" 

  • a 태그에 포함된 링크
  • 해당 링크를 클릭하면 지금 페이지의 이전 페이지의 정보를 가지고 온다
  • 예) 한국을 검색했고, 인기순으로 정렬후, 2번째 페이지를 찾아가기
    •  /?search='한국'&sorted=popular&p=2 
    • 여기서 만약에 정렬이 없으면 sort=으로 그냥 넘어간다