슈코딩

[Django] 장고 템플릿(Template) 문법 본문

코딩공부/Django

[Django] 장고 템플릿(Template) 문법

Roshu 2022. 6. 2. 15:56

 

장고 템플릿 언어

Flask에서 볼 수 있는 Jinja2 템플릿 엔진과 같은 형태인 기본적인 문법이 장고에서도 제공이 된다.

DB에서 데이터를 가져오거나, 복잡한 수식의 파이썬 코드 결과를 반환해야 할때, views.py 에서 작성해서 

템플릿으로 전달을 할 수 가 있다. 템플릿 변수, 템플릿, 필터 , 템플릿 코멘트 등이 있다.

 

템플릿 변수

템플릿 변수의 사용형식은 {{  }} 로 구성되있다.

{{ variable }}
  • 문자, 숫자, 언더바(_) 를 사용하여 변수를 정의
  • 변수의 속성에 접근하기 위한 dot(.) 표현도 가능
  • 정의되지 않은 변수를 만나면 빈 문자열('')을 반환. 이것은 settings.py  TEMPLATE_STRING_IF_INVALID 에서 변경할 수 있다.

 

템플릿 필터

변수에 필터를 적용 할 수 있다. 필터는 파이프 | 문자를 사용한다.

{{ name|lower }}  파이프 | 뒤에 'lower' 같은 것을 필터라고 한다.

 

  • lower : 모두 소문자로 변경
  • linebreaks : 해당문자를 p 태그로 묶어준다
  • safe : 특수문자를 escape 하지 않고 출력. ex) <div>TEST</div> 의 특수문자 <> 를 변환하지 않고 출력
  • truncatechars:5 : 앞에 5개 문자만 보여주고, 나머지는 말줄임
  • truncatewords:5 : 앞에 5개 단어만 보여주고, 나머지는 말줄임
  • default:"nothing" : 해당 변수 값이 False 거나 없거나 할때 보여주는 메세지
  • length: 변수의 개수를 출력
  • striptags : 변수의 html태그를 모두 삭제
  • add:"2" : 만약 변수값이 4라면 2를 더해준다. 문자열더하기 이므로 문자 "4" 가 오면 "42"가 된다.

 

탬플릿 태그

탬플릿 태그는 {%   %} 로 구성되어 있다.

텍스트 결과물을 만들기도 하고, 템플릿 로직제어, 외부 파일을 템플릿 내 로딩 등 가능하다.

<ul>
{% for a in as %}
	<li>{{ a.name }}</li>
{% endfor %}
</ul>

이처럼 파이썬 문법 for문을 템플릿내에서 사용할 수 있다. 이외에도 if 문도 {% if %} {% endif %} 사용할 수 있다.

 

{% csrf_token %}

  • CSRF 공격 방지 위한 태그, 장고는 내부적으로 CSRF 토큰값의 유효성을 검증한다.
  • <form> 태그 바로 첫줄에 작성을 한다.
<form method="POST">
        {# cross site request forgery -> 해킹 공격의 일종, 요청을 만들어서 실제 요청인것마냥 보내는것, 글을 100만개 쓰여지도록 요청을 만들 수도 있음 #}
        {% csrf_token %}
        <input name="title">
        <input name="content">
        <select name="category">
            {% for category in categories %}
            <option value="{{ category.name }}">{{ category.name }}</option>
            {% endfor %}
        </select>
        <button type="submit">글쓰기</button>
    </form>

 

{% url %}

  • html 소스에 URL 하드코딩하는 것을 방지
<body>
{# movie: 1, drama: 0 #}
    {% for name, count in infos.items %}
    <a href="{% url 'article' name %}">{{ name }}({{ count }})</a>
    {% endfor %}
    <a href="{% url 'new' %}">글쓰기</a>
</body>

{% with %}

  • with ~ endwith 내에서 특정 값을 변수에 저장해두는 기능
{% with total = apple.count %}
	{{ total }} apples in basket
{% endwith %}

 

{% load %}

  • 필터 및 사용자 정의 태그를 로딩해준다.

 

템플릿 상속 

  • 상속하는 부모 템플릿에서는 {% block %} {% endblock %} 태그 사용
  • 상속받는 자식 템플릿에서는 {% extends %} 태그를 상단에 표시
  • 페이지 마다 같은 nav 바가 있을시 중복되게 코드를 작성 할 필요가 없음.

base.html 을 작성하고 다른 html에 상속

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %} | spartaSNS</title>
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
            crossorigin="anonymous"></script>
    <style>
        .title-center {
            text-align: center;
            margin-top: 50px;
        }

        .wrap {
            width: 400px;
            margin: 0 auto;
        }

        .form-area {
            margin-top: 25px;
        }

        .timeline-container {
            margin-top: 25px
        }
    </style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container">
        <a class="navbar-brand" href="/">SpartaSNS</a>
        {% if user.is_authenticated %}
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav mr-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="/user"> 친구 <span class="sr-only"></span></a>
                    </li>
                </ul>
            </div>
        {% endif %}
        <form class="form-inline my-2 my-lg-0">
            {% if not user.is_authenticated %}
                <ul class="navbar-nav mr-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="/sign-in"> Sign In <span class="sr-only"></span></a>
                    </li>
                    <li class="nav-item active">
                        <a class="nav-link" href="/sign-up"> Sign Up <span class="sr-only"></span></a>
                    </li>
                </ul>
            {% else %}
                <ul class="navbar-nav mr-auto">
                    <li class="nav-item disabled">
                        <span class="nav-link">
                            {{ user.username }} 님 반갑습니다!!
                        </span>
                    </li>
                    <li class="nav-item active">
                        <a class="nav-link" href="/logout"> 로그아웃</a>
                    </li>
                </ul>
            {% endif %}
        </form>
    </div>
</nav>
{% block content %}

{% endblock %}

</body>
</html>

 

home.html

{% extends 'base.html' %}
{% block title %}
    메인페이지
{% endblock %}

{% block content %}
    <div class="container timeline-container">
        <div class="row">
            <!-- 왼쪽 컬럼 -->
            <div class="col-md-3">
                <div class="card">
                    <div class="card-body">
                        <h5 class="card-title">{{ user.username }}</h5>
                        <p class="card-text"> {{ user.bio }}</p>

                    </div>
                </div>
            </div>
            <!-- 오른 쪽 컬럼-->
            <div class="col-md-7">
                <!-- 글을 작성 하는 곳 -->
                <div class="row mb-2">
                    <div class="col-md-12">
                        <div class="card">
                            <div class="card-body">
                                <div class="media">
                                    <div class="media-body">
                                        <h5 class="mt-0">나의 이야기를 적어주세요</h5>
                                        <p>
                                        <form action="/tweet/" method="post">
                                            {% csrf_token %}
                                            {% if error %}
                                                <div class="alert alert-danger" role="alert">
                                                    {{ error }}
                                                </div>
                                            {% endif %}
                                            <div class="form-group mb-2">
                                                <textarea class="form-control" style="resize: none" name='my-content'
                                                          id="my-content"></textarea>
                                                <div class="mt-3 row">
                                                    <label for="tag"
                                                           class="col-sm-2 col-form-label">이 글의 태그</label>
                                                    <div class="col-sm-10">
                                                        <input type="text" class="form-control" name="tag" id="tag"
                                                               placeholder="콤마(,)로 구분 해 주세요">
                                                    </div>
                                                </div>
                                            </div>
                                            <button type="submit" class="btn btn-primary" style="float:right;">작성하기
                                            </button>
                                        </form>
                                        </p>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <hr>
                <!-- 작성 된 글이 나오는 곳 -->
                <div class="row">
                    {% for tw in tweet %}
                        <div class="col-md-12 mb-2">
                            <div class="card">
                                <div class="card-body">
                                    {% if tw.author == user %}
                                        <div style="text-align: right">
                                            <a href="/tweet/delete/{{ tw.id }}">
                                                <span class="badge rounded-pill bg-danger">삭제</span>
                                            </a>
                                        </div>
                                    {% endif %}
                                    <div style="text-align: right">
                                        <a href="/tweet/{{ tw.id }}">
                                            <span class="badge rounded-pill bg-success">보기</span>
                                        </a>
                                    </div>

                                    <div class="media">
                                        <div class="media-body">
                                            <h5 class="mt-0">{{ tw.content }}</h5>
                                            {% if tw.tags.all %}
                                                {% for tag in tw.tags.all %}
                                                    <a style="text-decoration: none"
                                                       href="{% url 'tagged_object_list' tag.name %}">
                                                    <span class="badge rounded-pill bg-success">
                                                        {{ tag.name }}
                                                    </span>
                                                    </a>
                                                {% endfor %}
                                                -<a style="text-decoration: none"
                                                    href="{% url 'tag_cloud' %}">TagCloud</a>
                                            {% endif %}
                                        </div>
                                        <div style="text-align: right">
                                            <span style="font-size: small">{{ tw.author.username }}-{{ tw.created_at|timesince }} 전</span>
                                        </div>

                                    </div>
                                </div>
                            </div>
                        </div>
                    {% endfor %}
                </div>
            </div>
            <div class="col-md-2"></div>
        </div>
    </div>
{% endblock %}

 

Comments