Programming

; develop a program

Framework/Django

[Django] 장고(Django) 서비스 개발 - 템플릿 필터

Clloud_ 2022. 12. 12. 12:16
반응형

이번 포스팅에서는 장고를 사용하여 게시판 서비스 개발에 필요한 템플릿 필터에 대하여 공부를 해보고자 한다.

 


템플릿 필터

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

 

필터란 일반적인 용어로 어떤 객체나 처리 결과에 추가적으로 명령을 적용하여 해당 명령에 맞게 최종 결과를 변경하는 것을 말한다.

템플릿 변수에 필터를 적용하여 변수의 출력 결과를 변경할 수 있다.

 

다음 예처럼 default_if_none과 같은 것들을 템플릿 필터라고 한다.

{{ form.subject.value|default_if_none:'' }}

 


게시물 번호 오류

현재 생성한 질문 목록 화면에는 한 가지 오류가 있다.

다음처럼 모든 페이지에서 게시물 번호가 항상 1부터 시작된다는 점이다.

 

 

두 번째 페이지로 이동하더라도 여전히 게시물 번호가 1부터 시작된다.

 

 


게시물 번호

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

이렇게 페이지별로 게시물의 번호를 역순으로 정렬하려면 다음과 같은 공식을 적용해야 한다.

 

번호 = 전체 건수 - 시작 인덱스 - 현재 인덱스 + 1

 

작 인덱스는 페이지당 시작되는 게시물의 시작 번호를 의미한다.

예를 들어 페이지당 게시물을 10건씩 보여준다면 1페이지의 시작 인덱스는 1, 2페이지의 시작 인덱스는 11이 된다.

현재 인덱스는 페이지에 보이는 게시물 개수만큼 0부터 1씩 증가되는 번호이다.

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

 

템플릿에서 이 공식을 적용하려면 빼기 기능이 필요하다.

앞에서 더하기 필터(|add:5)를 사용한 것처럼 빼기 필터(|sub:3)가 있으면 좋겠지만 장고에는 빼기 필터가 없다.

 

|add:-3 와 같이 숫자를 직접 입력하면 더하기 필터를 이용하여 원하는 값을 뺀 결과를 화면에 보여줄 수는 있다.

하지만 이 방법은 이곳에는 사용할 수 없다.

add 필터에는 변수를 적용할 수 없기 때문이다.

 

add 필터는 인수로 숫자만 가능하다.

 


 

템플릿 필터 작성하기

템플릿 필터를 작성하기 전에 템플릿 필터 파일을 저장할 templatetags 디렉터리가 필요하다.

projects\mysite\pybo\templatetags

 

templatetags 디렉터리는 반드시 앱 디렉터리(projects\mysite\pybo) 하위에 생성해야 한다.

mysite 디렉터리 아래에 만들면 안 되므로 위치에 주의해야 한다.

(mysite) c:\projects\mysite>cd pybo
(mysite) c:\projects\mysite\pybo>mkdir templatetags

 

templatetags 디렉터리에 pybo_filter.py 파일을 다음과 같이 작성한다.

 

[파일명: projects\mysite\pybo\templatetags\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)을 먼저 로드해야 한다.

{% load pybo_filter %}

 

템플릿 상단에 extends 문이 있을 경우 load문은 extends 문 다음에 위치해야 한다.

 

질문 목록 템플릿을 다음처럼 변경한다.

 

[파일명: projects\mysite\templates\pybo\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 %} 문을 상단에 적어주고 번호 부분을 위처럼 바꿨다.

상당히 복잡해 보이지만 번호 = 전체 건수 - 시작 인덱스 - 현재 인덱스 + 1 의 공식이 적용된 모습이다.

 

공식에 대응되는 코드

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

 

이와 같이 수정 후 게시물 번호를 확인해 보면 항상 1부터 시작했던 문제가 사라졌음을 확인할 수 있다.

 

 

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

 

 


반응형