• 티스토리 홈
  • 프로필사진
    조별하
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
조별하
  • 프로필사진
    조별하
    • 분류 전체보기 (124)
      • 1. 공부 (0)
        • 기술 면접 (0)
      • 2. 웹개발 (7)
        • Java (1)
        • IT 정보 (5)
        • Error 모음 (1)
      • 3. 개인관심 (1)
        • 전자 (1)
      • GITHUB (5)
      • IT 기술 면접 (3)
      • COMPUTER (2)
      • TASK (1)
      • LANGUAGES (20)
        • Python (3)
        • Django (6)
        • Java (7)
        • Node (1)
        • Jsp (2)
        • R (1)
      • 데이터과학 (2)
        • 머신러닝 및 딥러닝 (2)
      • DATABASE (5)
        • Oracle (2)
      • ISSUE (10)
        • Django (4)
        • Drf (2)
        • Javascript (1)
        • Git (1)
      • JAVA 교육 (65)
        • Java (3)
        • Jquery (2)
        • Sql (16)
        • Jdbc (1)
        • Db (2)
        • Jsp (9)
        • myWeb (15)
        • Servlet (4)
        • Spring (12)
        • Crawling (0)
        • Hosting (1)
      • 정보처리산업기사 (1)
      • EDUCATION (2)
        • IoT 서비스 (2)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • [Django] 다양한 템플릿 태그
        2023년 05월 04일
        • 조별하
        • 작성자
        • 2023.05.04.:01
        게시판과 페이징을 구현하며 템플릿 태그를 사용하였다.

        ✔️ {% csrf_token %}: 서버와 api 통신에 필요한 크로스 사이트 요청 위조를 방지하기 위해 사용되는 태그

        ✔️ {% if %}{% else %}: 조건을 이용하여 html에서 python 문법 사용 가능

        ✔️ {% for item in items %}: for 루프를 이용하여 html에서 python 문법 사용 가능

        🍃 순차적 출력 cycle

        ✔️ 게시판을 구현하면서 부트스트랩으로 디자인을 입히고, 짝수와 홀수 라인의 백그라운드 색상을 다르게 주었다.

        <table class="table table-striped">
                <thead>
                    <tr class="table-success">
                        <th>아이디</th>
                        <th>유저이름</th>
                        <th>이메일</th>
                        <th>가입일</th>
                        <th>페이플랜</th>
                        <th>가격</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user in users %}
                        <tr class={% cycle "" "table-dark" %}>
                            <td>{{ user.id }}</td>
                            <td>{{ user.username }}</td>
                            <td>{{ user.email }}</td>
                            <td>{{ user.date_joined }}</td>
                            <td>{{ user.pay_plan.name }}</td>
                            <td>{{ user.pay_plan.price }}</td>
                        </tr>
                    {% endfor%}
                    {% if users|length == 0 %} 조회할 데이터가 없습니다. {% endif %}
                </tbody>
        
            </table> 

        ✔️ 부트스트랩에서는 table 태그에 table-striped 클래스를 주면 아래와 같이 자동으로 짝수 홀수 백그라운드가 구분되며 디자인이 입혀졌다.

         

        ✔️ 이제 부트스트랩을 이용한 효과를 템플릿 태그로 다시 구현하려고 한다.

        <!--<table class="table table-striped">-->
        <table class="table">

        ✔️ 테이블 태그에 있는 table-striped 클래스를 제거한다.

                    {% for user in users %}
                        <tr class={% cycle "" "table-dark"%}>
                            <td>{{ user.id }}</td>
                            <td>{{ user.username }}</td>
                            <td>{{ user.email }}</td>
                            <td>{{ user.date_joined }}</td>
                            <td>{{ user.pay_plan.name }}</td>
                            <td>{{ user.pay_plan.price }}</td>
                        </tr>
                    {% endfor%}

        ✔️ for 루프로 렌더링하는 tr 태그에 {% cycle "" "table-dark" %} 템플릿 태그를 추가하여 첫 번째는 "" 빈 클래스가 두 번째는 table-dark 클래스가 번갈아가면서 나오게 한다.

         

        ✔️ 위의 코드를 변경 후 화면을 띄우면 아래와 같이 부트스트랩과 동일한 효과의 디자인이 입혀진 것을 확인 할 수 있다.(사실상 부트스트랩과 템플릿 태그의 조합이다.)

         

         

        🍃 template의 공통 영역 분리

        <!DOCTYPE html>
        <html lang="ko">
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
        
            <!-- Bootstrap CSS -->
            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
            <title>Index Page</title>
        </head>
        
        <!-- Option 1: Bootstrap Bundle with Popper -->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
        <body>

        ✔️ 대부분의 template에 상위의 header와 하위의 footer 등의 공통된 부분을 .html파일마다 중복으로 들어가는 경우가 있다.

         

        ✔️ 이렇게 중복되는 부분을 템플릿 태그 {% extendx %} 와 {% block %}{% endblock %} 를 이용하여 분리해보자.

         

        ➤ index.html

        <!DOCTYPE html>
        <html lang="ko">
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
        
            <!-- Bootstrap CSS -->
            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
            <title>Index Page</title>
        </head>
        
        <!-- Option 1: Bootstrap Bundle with Popper -->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
        <body>
            <h1>The is a Index Page</h1>
            <h3>{{ user }}</h3>
            {% if user.is_authenticated %}
                <a class="btn btn-primary" role="button" aria-disabled="true" href="/logout">로그아웃</a>
                <a class="btn btn-primary" role="button" aria-disabled="true" href="/user/list">유저목록</a>
                <a class="btn btn-primary" role="button" aria-disabled="true" href="/payplan/list">PayPlan목록</a>
            {% else %}
                <a class="btn btn-primary" role="button" aria-disabled="true" href="register">회원가입</a>
                <a class="btn btn-primary" role="button" aria-disabled="true" href="login">로그인</a>
            {% endif %}
            <br><br>
            {% block content %}
            {% endblock %}
        </body>
        </html>

        ✔️ 위의 .html파일은 게시판마다 공통으로 불러와야하는 부분이다.

         

        ✔️ 공통으로 들어가는 부분은 그대로 두고 변경되는 다른 template이 들어가는 부분에 아래의 코드를 추가해 준다.

        {% block content %} {% endblock %}

         

        ➤ boards.html

        {% extends "index.html" %}
        {% block content %}
        
            <h2>Pay Plan 리스트</h2>
            <h4>{% if msg %}{{msg}}{% endif %}</h4>
            <!-- <table class="table table-striped"> -->
            <table class="table">
                <thead>
                    <tr class="table-primary">
                        <th>아이디</th>
                        <th>이름</th>
                        <th>가격</th>
                        <th>생성일</th>
                    </tr>
                </thead>
                <tbody>
                    {% for plan in pay_plans %}
                        <!-- 부트스트랩 table-striped 대신 cycle 템플릿 태그 이용  -->
                        <tr class={% cycle "" "table-dark" %}>
                            <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>    
        ...
        {% endblock %}

        ✔️ 이제 게시판 .html에 들어가서 위와 같이 index.html에 중복으로 들어가있는 코드는 지워 준 후, 최 상단과 최 하단에 아래와 같은 코드를 붙여준다.


        {% extends "index.html" %}
        {% block content %}{% endblock %}

         

           

        ✔️ 두 개의 다른 게시판에서 index.html 부분이 공통으로 나오며 boards.html은 서로 다른 소스가 렌더링되는 것을 확인하였다.

         

        ✔️ 이렇게 템플릿 태그를 사용하면 소스코드를 절약할 수 있고, 템플릿 구조를 역할 별로 구조화 시킬 수 있다.

         

        🍃 다른 템플릿 추가 include

        ✔️ 특정 .html 파일을 생성 후 이 파일의 내용을 다른 template에 불러와서 사용할 수 있다.

         

        ➤ include.html

        <p>이 페이지는 인클루드 되었습니다.</p>

        ➤ boards.html

        ...
        </nav>
            {% include "include.html" %}
            <p>
                <a class="btn btn-primary" role="button" aria-disabled="true" href="{% url 'index' %}">홈으로</a>
                <a class="btn btn-primary" role="button" aria-disabled="true" href="{% url 'register' %}">회원가입</a>
            </p>
        ...

         

        ✔️ 위와 같이 특정 템플릿을 만든 후 그 템플릿을 불러오고 싶은 template에 아래와 같은 코드를 추가 하면 특정 템플릿의 코드를 불러와서 사용할 수 있다.

        {% include "include.html" %}

         

        ✔️ 위의 템플릿 태그는 공통된 것이 아닌 팝업이나 특정 html을 불러와서 보여줄 때 사용할 수 있다.

         

        🍃 템플릿 필터

        1. 사용자 정의 템플릿 태그

        ✔️ 지금까지는 Django에서 제공되는 템플릿 태그를 사용해보았다.

         

        ✔️ 하지만 웹 개발에 있어 Django에서 제공되는 태그만 사용해서 모든 것을 다 구현할 수 없기 때문에, 사용자 정의로 만든 태그가 필요한 경우가 있을 것이다.

         

         

        ✔️ 현재 출력된 데이터는 유저명, 이메일, 가입일, 페이플랜, 가격 등의 필드 데이터 이다.


        ✔️ 이메일은 @가 붙은 이메일 형식의 필드이지만 제 3자가 보았을 때 스팸메일을 보내거나 악용하는 경우가 있을 수 있으며,

        ✔️ 가입일은 서버에서 등록되는 데이터이기 때문에 년/월/일 뿐 아니라 시간까지 들어 있다.

        ✔️ 또한 가격은 정수형으로 데이터가 저장되어 있기 때문에 천자리 수가 구분이 되지 않아

         

        ✔️ 위와 같은 정제되지 않는 데이터를 그대로 보여주게 되면 사용자는 가독성이 떨어질 수 있으므로 내가 정의한 형식으로 데이터에 필터를 걸 수 있게 템플릿 태그를 만들어 보자.

         

        2. 템플릿 태그 생성과 필터 적용

        ✔️ 프로젝트 App안에 templatetags 폴더를 생성 후, 내부에 __init__.py, custom_tags.py 파일을 만들어 주자.

         

         

        ✔️ 위에서 언급한 것과 같이 이메일, 가입일, 가격 3개의 필드를 커스텀 필터를 걸어 보겠다.

         

        📌 이메일
        templatetags > custom_tags.py

        from django import template
        
        register = template.Library()
        
        @register.filter(name="email_ma")
        def email_masker(value):
            email_split = value.split("@")
        
            return f"{email_split[0]}@******.***"

        ✔️ django의 template모듈 사용을 위해 template.Library()

        ✔️ "email_ma"라는 명칭으로 filter를 적용
        - email_masker 함수명으로 필터를 적용시키지 않기위한 설정

        ✔️ 이메일 형식의 @ 이후 부분을 split함수로 잘라내어 뒷부분은 masker 처리

         

        user > boards.html 

        {% load custom_tags %}
        
                    {% for user in users %}
                        <tr class={% cycle "" "table-dark" %}>
                            <td>{{ user.id }}</td>
                            <td>{{ user.username }}</td>
                            <td>{{ user.email|email_ma }}</td>
                            <td>{{ user.date_joined }}</td>
                            <td>{{ user.pay_plan.name }}</td>
                            <td>{{ user.pay_plan.price }}</td>
                        </tr>
                    {% endfor%}

        ✔️ "|"를 붙여 내가 정의한 태그 명칭을 뒷 부분에 붙여서 아래와 같이 수정하면 클라이언트 렌더링 시 email은 내가 정의한 함수를 거쳐 필터링 된다.

        {{ user.email|email_ma }}

         

         

        📌 가격
        templatetags > custom_tags.py

        from django import template
        from django.utils.safestring import mark_safe
        
        register = template.Library()
        
        @register.filter(name="price_comma")
        def price_comma(value):
            return format(value, ',d')

        ✔️ 숫자 천자리 수 마다 ","가 붙게 데이터를 정제하기 위해 함수 정의

        ✔️ format() 함수를 사용하여 첫 번째 인자는 값, 두 번째 인자는 ',d/f'
        - d또는 f 중 하나만 넣어주면 되는데 d 는 정수 f 실수를 의미한다.

         

        user > boards.html 

        {% load custom_tags %}
                    {% for user in users %}
                        <tr class={% cycle "" "table-dark" %}>
                            <td>{{ user.id }}</td>
                            <td>{{ user.username }}</td>
                            <td>{{ user.email|email_ma }}</td>
                            <td>{{ user.date_joined }}</td>
                            <td>{{ user.pay_plan.name }}</td>
                            <td>{{ user.pay_plan.price|price_comma }}</td>
                        </tr>
                    {% endfor%}

        ✔️ 이메일과 동일하게 아래와 같이 수정

           {{ user.pay_plan.price|price_comma }}

         

        📌 가입일


        ✔️ 가입일의 경우는 내가 정의한 것이 아닌 제공되는 필터를 사용하여 날짜에 대한 데이터를 정제해 보겠다.

        user > boards.html

        ...
        
        {{ user.date_joined|date:"Y M d D" }}
        
        ...

        ✔️ 위에서 사용한 "date" 태그는 따로 정의한 태그가 아니지만 기본적으로 django에서 제공하기 때문에 사용이 가능한다.

         

        ✔️ "Y"는 년도, "M"은 월, "d"는 일자, "D"는 요일을 의미한다.

         

        ✔️ 상세한 date에 대한 조건은 공식문서에 다양하게 나와 있으니 확인 바란다.

        참고 : Django 공식 문서

         

        Django

        The web framework for perfectionists with deadlines.

        docs.djangoproject.com

         

         

        2. 기타 필터 적용 방법

        ✔️ 필터를 적용할 때, 인자를 추가로 보내 데이터 처리에 사용할 수 있다.

         

        📌 인자 추가
        user > boards.html

        {% load custom_tags %}
        ...
        
            <td>{{ user.email|email_ma:user.id }}</td>
        
        ...

        ✔️ 위와 같이 정의한 "email_ma"태그 뒤에 :[보내고 싶은 인자]를 붙여 준다.

         

        templatetags > custom_tags.py

        from django import template
        
        register = template.Library()
        
        @register.filter(name="email_ma")
        def email_masker(value, arg):
            email_split = value.split("@")
        
            return f"{email_split[0]}@******.***" if arg % 2 == 0 else value 

        ✔️ 위에서 작성한 코드를 조금 수정하였는데, 매개변수 arg를 추가 한 후, 클라이언트에서 전달 받은 user.id값이 짝수, 홀수에 따라 이메일 뒤의 masker처리를 주었다가 안주게 코드를 변경해 보았다.

         

        ✔️ 결과는 아래와 같이 나온다.

         

        3. filter vs simple_tag

        ✔️ 위에서 태그의 명칭을 정할 때 "filter"를 사용하여 아래와 같이 사용하였다.

        from django import template
        
        register = template.Library()
        
        @register.filter(name="email_ma")
        def email_masker(value, arg):
            ...

        ✔️ 위의 filter와 동일한 기능을 하는 simple_tag도 사용할 수 있는데 두개의 차이점이 존재한다.

         

        ✔️ filter를 사용하면 필터링할 값과 추가 인자를 1개 받을 수 있다.

         

        ✔️ 하지만 simple_tag를 사용하면 인자의 개수에 제한 없이 넘겨 줄 수 있다.

        from django import template
        from django.utils.safestring import mark_safe
        
        register = template.Library()
        
        # takes_context를 True로 설정하지 않으면 메소드에서 context를 사용할 수 없음
        @register.simple_tag(name="test_tags", takes_context=True)
        def test_tags(context):
            tag_html = "<span class='badge badge-primary'>테스트 태그</span>"
        
            # 클라이언트로 전달 시 스트링만 보내게 되면 html 태그로 인식하지 못함
            return mark_safe(tag_html)

        ✔️ 위는 simple_tag를 사용해보기 위해 만든 함수이며 filter와 동일하게 사용자 정의 템플릿 태그를 만들 수 있다.

         

        ✔️ 코드는 필터를 거는 것 뿐 아니라 html를 전달하여 렌더링 할 수 있는지 확인하는 내용이다.

         

        🍃 참고

        filter vs simple_tag

         

        Django template filters, tags, simple_tags, and inclusion_tags

        This is more of a general question about the distinctions between these four different kinds of django tags. I just read the documentation page on template tags: http://docs.djangoproject.com/en/dev/

        stackoverflow.com

        장고 공식 문서

         

        Django

        The web framework for perfectionists with deadlines.

        docs.djangoproject.com

        https://itinerant.tistory.com/161

         

        [Django] Django custom template tags

        [Django] Django custom template tags Django에서 제공하는 django templates의 한계를 극복, 개발자가 직접 template를 제작하여 사용할 수 있다. - custom template_tags는 반드시 앱 안의 "templatetags"폴더 안에 생성해야

        itinerant.tistory.com

         

         

        저작자표시 (새창열림)

        'LANGUAGES > Django' 카테고리의 다른 글

        [Django] django-crontab 스케줄러 작성  (0) 2023.05.22
        [Docker] docker-compose를 이용한 프로젝트 배포  (0) 2023.05.08
        [Django] django-seed를 이용한 데이터 만들기  (0) 2023.05.03
        [Django] Django 커스텀 커맨드 만들기  (0) 2023.05.02
        [Django] debug_toolbar 사용하기  (0) 2023.04.06
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바