[Django] 파이보 서비스 개발 - 템플릿 필터

싱숭생숭어·2023년 5월 9일
0

Django

목록 보기
17/19
post-thumbnail

위 글은 점프 투 장고를 참고해 작성하였습니다.

템플릿 필터란 템플릿 태그에서 | 문자 뒤에 사용하는 필터를 말함 !

여기에서 {{ form.subject.value|default_if_none:'' }} default_if_none과 같은 것들이 템플릿 필터 ~

이 포스팅에서는 이러한 템플릿 필터를 직접 만들고 사용해보자.


게시물 번호 오류

파이보 질문 목록 화면에는 한가지 오류가 있음

바로 모든 페이지에서 게시물 번호가 항상 1부터 시작된다는 것 !

첫번째 페이지에서는 게시물 번호가 1 - 10 까지

두번째 페이지에서도 여전히 게시물 번호가 1 - 10 까지


게시물 번호

게시물 전체 건수가 12개라면, 첫번째 페이지는 번호가 12~3까지 역순으로 보여지고, 두번째 페이지에는 2~1까지 보여져야 한다. (만든 시간 순으로 게시물 번호 지정)

페이지별로 게시물의 번호를 역순 정렬하는 공식
번호 = 전체건수 - 시작인덱스 - 현재인덱스 + 1

  • 시작인덱스 : 페이지당 시작되는 게시물의 시작 번호

    • 페이지당 게시물을 10건씩 보여준다면 2페이지의 시작인덱스는 11
  • 현재인덱스 : 페이지에 보여지는 게시물 개수만큼 0부터 1씩 증가되는 번호

-> 따라서 전체 게시물 개수가 12개이고 페이지당 10건씩 게시물을 보여준다면, 공식에 의해 1페이지의 번호는 12 - 1 - (0~9) + 1으로 12~3까지 표시되고, 2페이지의 번호는 12 - 11 - (0~1) + 1이 되어 2~1이 표시될 것 !

이 공식을 템플릿에 적용하려면 빼기 기능이 필요하다. 하지만 장고에는 빼기 필터가 없다. 기존에 존재하는 더하기 필터를 활용해 |add:-3와 같이 숫자를 직접 입력해 원하는 값을 뺀 결과를 출력할 수 있지만, add 필터에는 변수를 적용할 수 없기 때문에 이 경우에는 사용할 수 없다.(add 필터는 인수에 숫자만 가능하다.)


템플릿 필터 작성하기

템플릿 필터를 작성하기 전에 앞서, 템플릿 필터 파일을 저장할 templatetags 디렉터리를 생성

위치는 projects\mysite\pybo\templatetags 처럼 반드시 ! 앱 디렉터리(projects\mysite\pybo) 하위에 생성해야 함 ! mysite 프로젝트 디렉터리 하위에 만들면 안되므로 주의할 것.

그리고 templatetags 디렉터리에 pybo_filter.py 파일을 다음과 같이 생성

pybo_filter.py안의 내용은 다음과 같이 작성

from django import template

register = template.Library()


@register.filter
def sub(value, arg):
    return value - arg
  • 템플릿 필터 함수를 만드는 방법은 위와 같다.

  • 위처럼 sub 함수에 @register.filter 라는 에너테이션을 적용하면 템플릿에서 해당 함수를 필터로 사용가능해짐

    • 여기서 에너테이션이란 spring 용어, 파이썬에서는 데코레이터라고 지칭, 같은 의미로 이해하기 !
  • sub함수는 기존 값 value에서 입력으로 받은 값 arg를 빼서 리턴하는 함수


템플릿 필터 사용하기

작성한 sub 필터를 템플릿에서 사용해보자.

sub 필터를 사용하기 위해서는 템플릿 상단에 {% load pybo_filter %} 로 sub 필터를 저장한 파일(pybo_filter.py)을 먼저 로드해야 함

  • 이때 템플릿 상단에 extends 문이 있을 경우 load 문은 extends 문 다음에 위치해야 함 !

질문 목록 템플릿(question_list.html)을 다음과 같이 변경

{% extends 'base.html' %}
{% load pybo_filter %} <!-- 이 부분 추가-->
{% block content %}
<div class="container my-3">
    <table class="table">
        <thead>
        <tr class="table-dark">
            <th>번호</th>
            <th>제목</th>
            <th>작성일시</th>
        </tr>
        </thead>
        <tbody>
        {% if question_list %}
        {% for question in question_list %}
        <tr>
            <td>
                <!-- 번호 = 전체건수 - 시작인덱스 - 현재인덱스 + 1 -->
                {{ question_list.paginator.count|sub:question_list.start_index|sub:forloop.counter0|add:1 }}
            </td> <!-- 여기까지 추가-->
            <td>
                <a href="{% url 'pybo:detail' question.id %}">{{ question.subject }}</a>
            </td>
            <td>{{ question.create_date }}</td>
        </tr>
(... 생략 ...)

위의 코드를 다시 말하면 상단에 {% load pybo_filter %}를 적어주고

<td>{{ forloop.counter }}</td>

이전에 위와 같던 인덱스 번호 부분을

<td>
                <!-- 번호 = 전체건수 - 시작인덱스 - 현재인덱스 + 1 -->
                {{ question_list.paginator.count|sub:question_list.start_index|sub:forloop.counter0|add:1 }}
            </td>

이렇게 바꿔주었다 ! 앞서 말한 번호 = 전체건수 - 시작인덱스 - 현재인덱스 + 1 의 공식이 적용된 모습이다.

  • 공식코드
    전체건수question_list.paginator.count
    시작인덱스question_list.start_index
    현재인덱스forloop.counter0

위와 같이 템플릿 파일을 수정 후, 로컬 서버를 재가동해 페이지를 확인해보면

항상 게시물 번호가 1부터 시작했던 문제가 사라졌음을 확인할 수 있다 !!

두번째 페이지로 이동하더라도 다음처럼 그 이후의 번호가 표시되는 것도 볼 수 있다 !!

profile
공부합시당

0개의 댓글