11. -1 HomeView - 수동

조재훈·2022년 7월 24일
0

Clone_Airbnb

목록 보기
23/31
post-thumbnail

1) Template

이 모든 목록이 전부 한 페이지에 뜨게 하는건 좀 아니다. 페이지를 구분해주자.

우선 첫 5개만 끊어보자.
rooms - views.py - all_rooms

    all_rooms = models.Room.objects.all()[:5]


이런 식으로 첫 페이지에서는 1~5번째, 그 다음 페이지에서는 6~10번째 순으로 차근차근 보여주게 하자.
SQL에서 5개씩 제한하는거는 LIMIT 5이다. 이런식으로 조각을 내면 새로운 쿼리셋이 반환된다.
https://docs.djangoproject.com/en/4.0/topics/db/queries/

보통 페이지를 변경할 때 url에 page=1, page=2 이런 식으로 바꿔가며 뜨게 된다.
url에서 오는 모든 것들은 get request이다. get이 뭔지 보자.
rooms - views.py - all_rooms

    print(request.GET)

URL


원하는 값들을 넣을 수 있다.


request.GET 안에 뭐가 들었는지 살펴보자.

    print(dir(request.GET))


keys를 확인해보자.

    print(request.GET.keys())


딕셔너리의 키가 반환되었다.
get을 확인해보자.

    print(request.GET.get())

인자가 하나 필요한데 없다고 한다. key값을 넣어주어야 한다.


key 값을 넣어서 다시 해보자.

    print(request.GET.get("page"))


URL에서 page에 해당하는 숫자가 콘솔에 나타났다.

city로 바꿔보면 seoul이 나타난다.

    print(request.GET.get("city"))

이를 이용해서 url에 입력된 페이지를 가져올 수 있다. 가져올 key값으로 page를 설정하고 기본값은 1로 한다.

def all_rooms(request):
    page = request.GET.get("page", 1)
    page_size = 10
    limit = page_size * page
    offset = limit - page_size
    all_rooms = models.Room.objects.all()[offset:limit]
    return render(request, "rooms/home.html", context={"rooms":all_rooms},)

'ㅅ'

아하. offset을 구할때 뺄셈을 하는데 숫자가 아니라 문자열이 들어갔다는 내용이다.

int로 변환해주자

    page = int(request.GET.get("page", 1))

잘된다!

url에서 page를 2로 바꿔주니 내용도 바뀌었다!

문제는 적절한 페이지를 넘어가버려도 오류가 안나고 계속 뜬다.

페이지 번호를 지워보자.

누군가가 억지로 해당 url로 접근시 에러도 에러인데 기본 페이지로 돌아가게 해주는게 나을것이다. 기본 페이지값을 지정해주자. 그리고 이 page값을 템플릿으로 넘겨줄 것이다.
rooms - views.py

def all_rooms(request):
    page = request.GET.get("page", 1)
    page = int(page or 1)
    page_size = 10
    
    ...
    
    return render(
        request,
        "rooms/home.html",
        context={
            "rooms": all_rooms,
            "page": page,
        },
    )

page = request.GET.get("page", 1)

=> url에서 GET으로 가져오는 key값인 "page"의 기본값

page = int(page or 1)

=> 페이지 로직을 처리할 때 비어있으면 주어지는 기본값

그리고 템플릿으로 넘어온 page 변수를 화면에 출력하자.
templates - rooms - home.html

{% block content %}
    {% for room in rooms %}
        <h1>{{room.name}} / ${{room.price}}</h1>
    {% endfor %}
    
    Page {{page}}
{% endblock content %}

이제 page를 입력하지 않았을 때 기본값으로 page=1이 뜨게 되며, 하단에 page 번호도 출력된다.

전체 몇 페이지 중에서 현재 페이지인지 확인해보자.
templates - rooms - home.html

{% block content %}
    {% for room in rooms %}
        <h1>{{room.name}} / ${{room.price}}</h1>
    {% endfor %}
    
    Page {{page}} of {{page_count}}
{% endblock content %}

ForeignKey를 가진 모델의 경우 Manager를 통해 그 인스턴스의 변수들에 접근할 수 있다. 이 Manager는 QuerySets를 반환하는데 count()라는걸 써서 그 내용물 갯수를 셀 수 있다.
https://docs.djangoproject.com/en/4.0/topics/db/queries/


rooms - views.py - all_rooms


...

	page_count = models.Room.objects.count() / page_size
    return render(
        request,
        "rooms/home.html",
        context={
            "rooms": all_rooms,
            "page": page,
            "page_count": page_count,
        }
    )

10.2 페이지!

11페이지로 가보면 역시 2개밖에 안뜬다.

이를 해결하기 위해 ceil 함수를 쓴다. 천장이란 의미로써 소수점을 버림한다.
rooms - views.py - all_rooms

from math import ceil

...

    page_count = ceil(models.Room.objects.count() / page_size)
    return render(
        request,
        "rooms/home.html",
        context={
            "rooms": all_rooms,
            "page": page,
            "page_count": page_count,
            "page_range": range(1, page_count),
        }

템플릿도 수정해준다. page_range를 추가해 각 페이지 번호가 뜨도록 하고 그 페이지마다 링크도 걸어준다.
templates - rooms - home.html


...
    
    <h5>Page {{page}} of {{page_count}}<h5>
    
    {% for page in page_range %}
        <a href="?page={{page}}">{{page}}</a>
    {% endfor %}

{% endblock content %}

2) 버튼 추가

현재 페이지 좌우로 이전/다음 페이지 버튼이 나오게 해보자.
templates - rooms - home.html

    ...
    
    <h5>
      <a href="?page={{page-1}}">Previous</a>
      Page {{page}} of {{page_count}}
      <a href="?page={{page+1}}">Next</a>
    </h5>

하지만 안된다. 템플릿안에 +나 -연산 못한다고 한다.

이럴땐 built-in filter 라는걸 써보자. (내장필터?)
https://docs.djangoproject.com/en/4.0/ref/templates/builtins/#built-in-filter-reference

templates - rooms - home.html

    ...
    
    <h5>
      <a href="?page={{page|add:-1}}">Previous</a>
      Page {{page}} of {{page_count}}
      <a href="?page={{page|add:1}}">Next</a>
    </h5>

오 나온다

하지만 페이지가 멈추지않고 넘어가는 문제가 있다.

1번째 페이지일때는 Previous를 없애고 마지막 페이지에서는 Next를 없애는 식으로 해결하겠다. 그러려면 조건문이 필요하다.
templates - rooms - home.html

    ...
    
    <h5>
      {% if page is not 1 %}
          <a href="?page={{page|add:-1}}">Previous</a>
      {% endif %}
      
      Page {{page}} of {{page_count}}
      
      {% if page is not page_count %}
          <a href="?page={{page|add:1}}">Next</a>
      {% endif %}
    </h5>

page = 1 일때


물론 url을 직접 쳐서 다른 페이지로 이동하면 위의 연산이 안먹히는 문제가 있다. 그러나 일단 그건 다음에 해보기로 하자. 할게 너무 많아서....

profile
맨땅에 헤딩. 인생은 실전.

0개의 댓글