위 글은 점프 투 장고를 참고해 작성하였습니다.
템플릿 필터란 템플릿 태그에서 |
문자 뒤에 사용하는 필터를 말함 !
여기에서 {{ form.subject.value|default_if_none:'' }}
default_if_none
과 같은 것들이 템플릿 필터 ~
이 포스팅에서는 이러한 템플릿 필터를 직접 만들고 사용해보자.
파이보 질문 목록 화면에는 한가지 오류가 있음
바로 모든 페이지에서 게시물 번호가 항상 1부터 시작된다는 것 !
첫번째 페이지에서는 게시물 번호가 1 - 10 까지
두번째 페이지에서도 여전히 게시물 번호가 1 - 10 까지
게시물 전체 건수가 12개라면, 첫번째 페이지는 번호가 12~3까지 역순으로 보여지고, 두번째 페이지에는 2~1까지 보여져야 한다. (만든 시간 순으로 게시물 번호 지정)
페이지별로 게시물의 번호를 역순 정렬하는 공식
번호 = 전체건수 - 시작인덱스 - 현재인덱스 + 1
시작인덱스 : 페이지당 시작되는 게시물의 시작 번호
현재인덱스 : 페이지에 보여지는 게시물 개수만큼 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
라는 에너테이션을 적용하면 템플릿에서 해당 함수를 필터로 사용가능해짐
sub함수는 기존 값 value에서 입력으로 받은 값 arg를 빼서 리턴하는 함수
작성한 sub 필터를 템플릿에서 사용해보자.
sub 필터를 사용하기 위해서는 템플릿 상단에 {% load pybo_filter %}
로 sub 필터를 저장한 파일(pybo_filter.py
)을 먼저 로드해야 함
질문 목록 템플릿(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부터 시작했던 문제가 사라졌음을 확인할 수 있다 !!
두번째 페이지로 이동하더라도 다음처럼 그 이후의 번호가 표시되는 것도 볼 수 있다 !!