Django 게시판

Gom La·2023년 5월 2일
0

장고와 친해지기

목록 보기
11/17
post-thumbnail

📌 데이터 작업

게시판을 구현하기 위해선 보여 줄 수 있는 데이터가 있어야 한다. 물론 게시글 등록 기능을 구현 후 데이터를 넣을 수도 있지만, 등록/현황 화면을 구현 후 데이터를 넣어야하기 때문에 사전에 미리 데이터를 생성해 보려고 한다.

➤ Django-seed

django-seed 설치

# 설치
pip3 install django-seed
pip3 install psycopg2
pip3 freeze > requirements.txt

데이터 작업

# shortener App에 있는 모델에 30개 데이터 추가
python3 manage.py seed shortener --number=30

먼저 django-seed를 설치 후 shortener 내가 생성한 App에 데이터를 생성해 보자.

위의 명령어로 바로 데이터를 생성하면 데이터가 무작위로 생성된 것을 확인할 수 있는데, 원하는 데이터를 넣기 위해선 코드로 작성하여 원하는 데이터의 형태가 생성될 수 있게 커스텀을 해야한다.

커스텀하여 원하는 데이터를 만드는 방법은 학습 후 작성해 보려고 한다.

💡 단, App을 통해서 데이터를 생성하는 과정이라 하나의 모델에만 데이터를 생성하기 위해서는 커스텀하여 데이터를 만들어야 한다.


📌 게시판 구현

➤ URL 라우팅

urlpatterns = [
	...
    
    # LIST
    path('payplan/list', payplan_list_view, name='playplan_list'),
    path('user/list', user_list_view, name='user_list'),
]

User와 Pay Plan의 현황을 조회할 수 있는 게시판을 만들기 위해 2개의 URL을 작성

➤ VIEW 코드 작성

User

def user_list_view(request):
    page = int(request.GET.get("page", 1))
    users = Users.objects.all().order_by("-id")
    paginator = Paginator(users, 5)
    users = paginator.get_page(page)

    return render(request, "user/boards.html", {"users": users})

Payplan

def payplan_list_view(request):
    page = int(request.GET.get("page", 1))
    pay_plans = PayPlan.objects.all().order_by("-id")
    paginator = Paginator(pay_plans, 5)
    pay_plans = paginator.get_page(page)

    return render(request, "payplan/boards.html", {"pay_plans": pay_plans})

두 개의 view 모두 User와 Pay Plan의 조회 URL 요청 시 응답을 주기 위해 처리되는 코드이다.

조회 되는 데이터를 한 번에 다 보여주게 되면 데이터가 많을 시 찾기가 힘들기 때문에 Pagenator를 사용하여 페이징 처리를 해야한다.

  1. page: 페이지 num를 클릭 할 때 클라이언트에서 넘겨 받는 페이지 num값을 할당

  2. pay_plans, users: 현황에 조회할 Pay Plan 과 User의 데이터를 조회하여 정렬하여 할당

  3. paginator: Paginator객체를 이용하여 조회 데이터와 한 페이지에 렌더링할 데이터 갯수를 인자로 호출

Paginator 클래스는 아래의 매개변수를 받는다.

  • object_list : 페이징처리할 데이터 리스트(필수)

  • per_page: 한 페이지에 보여줄 데이터 개수(필수)

  • orphans: 아래에 공식 문서를 참고하여 옵션 내용을 작성(옵션)

    Paginator.orphans¶
    Optional. Use this when you don’t want to have a last page with very few items.

    옵션. 마지막페이지에 매우 조금의 데이터만 남기는 것이 싫을 때 사용하는 옵션이다.

    If the last page would normally 
    have a number of items less than or equal to orphans,
    then those items will be added to the previous page 
    (which becomes the last page) instead of leaving the items on a page by themselves. 

    만약 마지막 페이지에 orphans 보다 적거나 orphans 의 값과 동일한 데이터가 남는다면, 이 데이터를 전 페이지에 추가하여 함께 보여준다.

    For example, with 23 items, per_page=10, and orphans=3, 

    예를들어 데이터가 23개이며 한 페이지에 10개씩 보여주고 orphans 옵션을 3으로 설정하였다.

    there will be two pages; 
    the first page with 10 items and the second (and last) page with 13 items. 
    orphans defaults to zero, which means pages are never combined and the last page may have one item.

    그러면 2개의 페이지가 될것이며, 첫번째 페이지는 10개 두번째, 즉 마지막 페이지는 10+3개가 된 13개의 데이터를 가지며 페이지를 보여줄 것이다.

    orphans 의 기본 값은 0이며 마지막 데이터가 1개만 남더라도 이전 페이지에 포함되지 않는다.

    출처 : Django 공식문서 - Paginator.orphans

  • allow_empty_first_page: 첫 번째 페이지를 비울 수 있는지에 대한 여부이다. 만약 False로 설정하여 object_list, 매개변수 list가 비어있으면 오류가 발생한다.(옵션)

  1. pay_plans, users: Paginator클래스를 이용하여 정제한 데이터를 다시한 번 할당 후 클라이언트로 전달

➤ html 템플릿 문법 처리

<!DOCTYPE html>
<html lang="ko">
<head>
    <title>Pay Plan 리스트</title>
</head>
<body>
    <h2>Pay Plan 리스트</h2>
    <h4>{% if msg %}{{msg}}{% endif %}</h4>
    <table>
        <thead>
            <th>아이디</th>
            <th>이름</th>
            <th>가격</th>
            <th>생성일</th>
        </thead>
        <tbody>
            {% for plan in pay_plans %}
                <tr>
                    <td>{{ plan.id }}</td>
                    <td>{{ plan.name }}</td>
                    <td>{{ plan.price }}</td>
                    <td>{{ plan.create_at }}</td>
                </tr>
            {% endfor%}
            {% if pay_plans|length == 0 %} 조회할 데이터가 없습니다. {% endif %}
        </tbody>
        
    </table>    
    <nav>
        <ul>
            {% if pay_plans.has_previous %}
            <li>
                <a href="?page={{ pay_plans.previous_page_number }}">이전</a>
            </li>
            {% else %}
            <li>
                <a href="#">이전</a>
            </li>
            {% endif %}
            <li>
                <a href="#">{{ pay_plans.number }} / {{ pay_plans.paginator.num_pages }}</a>
            </li>
            {% if pay_plans.has_next %}
            <li>
                <a href="?page={{ pay_plans.next_page_number }}">다음</a>
            </li>
            {% else %}
            <li>
                <a href="#">다음</a>
            </li>
            {% endif %}
        </ul>
    </nav>
    <p>
        <a href="{% url 'index' %}">홈으로</a>
        <a href="{% url 'register' %}">회원가입</a>
    </p>
</body>
</html>

table태그로 해더는 고정으로 처리 후 템플릿 문법으로 서버에서 전달받은 데이터 객체를 반복문 loop를 이용하여 동적으로 렌더링해준다.

서버에서 전달받은 데이터 객체는 이전 페이지와 다음 페이지에 대한 정보가 담겨있다.

  • has_previous: 이전 페이지 유무
  • previous_page_number: 이전 페이지 number
  • number: 현재 페이지 number
  • paginator.num_pages: 정제한 데이터로 나오는 페이지 수
  • has_next: 다음 페이지 유무
  • next_page_number: 다음 페이지 number

➤ 결과

다음과 같이 페이지가 7개가 나오며 각 페이지당 위에서 설정한 5개의 데이터가 출력되는 것을 확인이 가능하다.

물론 마지막 페이지는 총 페이지 개수에서 2개가 모자라기 때문에 남은 개수로만 출력이 된다.

➤ Paginator - orphans 옵션 확인

def payplan_list_view(request):
    ...
    # paginator = Paginator(pay_plans, 5)
    
    # orphans 옵션 추가
    paginator = Paginator(pay_plans, 5, orphans=1)
    ...

    return render(request, "payplan/boards.html", {"pay_plans": pay_plans})

위와 같이 Paginator에 orphans옵션을 1로 설정 후 게시판이 어떻게 출력되는지 확인해 보겠다.

이전의 페이징은 7페이지가 나왔는데 6페이지가 나오는 것을 확인할 수 있으며 코드에서 5개 데이터를 설정한 것과 다르게 마지막 페이지에서는 6개의 데이터가 렌더링 된 것을 확인 할 수 있다.

마지막 1개의 데이터가 전 페이지로 이전되어 한 번에 보여준 것이다.

profile
인생 개발자 라곰!!

0개의 댓글