Templates

  • Template ์–ธ์–ด๋Š” ๊ฐ framework ๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค

  • Django์˜ template ์–ธ์–ด๋Š” DTL !

DTL (Django Template Language)

Ground Rule

: ์—ฐ์‚ฐ์€ DTL์ด ์•„๋‹Œ views.py ์˜ context๋กœ ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ DTL์€ ๋‹จ์ˆœํžˆ ์ถœ๋ ฅํ•˜๋Š” ์—ญํ• ๋งŒ ํ•˜๊ฒŒ ํ•˜๊ธฐ

๊ธฐ๋ณธ ๋ฌธ๋ฒ•

1. ์ถœ๋ ฅ {{ }}

{{ menu }}
{{ menu.0 }}

2. ๋ฌธ๋ฒ• {% %}

{% for menu in menus %}

{% endfor %}

3. ์ฃผ์„ ``

{# This is comment #}

๋ฐ˜๋ณต๋ถ„

Loops over each item in an array

{% for reply in replies %}
    <p> {{reply}} </p>
{% endfor %}
  • {{ forloop.counter }}

  • {{ forloop.counter0 }}

  • `

    `

    : ๋ฐฐ์—ด์ด ๋น„์–ด์žˆ์œผ๋ฉด ์ถœ๋ ฅํ•  ๋‚ด์šฉ ์จ์ค„ ๋•Œ ์‚ฌ์šฉ

Loop over each item in a dictionary

{% for key, value in data.items %}
    {{ key }}: {{ value }}
{% endfor %}

Variable

Description

forloop.counter

The current iteration of the loop (1-indexed)

forloop.counter0

The current iteration of the loop (0-indexed)

forloop.revcounter

The number of iterations from the end of the loop (1-indexed)

forloop.revcounter0

The number of iterations from the end of the loop (0-indexed)

forloop.first

True if this is the first time through the loop

forloop.last

True if this is the last time through the loop

forloop.parentloop

For nested loops, this is the loop surrounding the current one

์กฐ๊ฑด๋ฌธ

{% if user == 'admin' %}
    <p> Accessible</p>
{% else %}
    <p> Inaccessible</p>
{% endif %}

built-in tag, filter (|)

๊ณต์‹๋ฌธ์„œ ์ฐธ๊ณ ํ•˜์ž : https://docs.djangoproject.com/en/3.0/ref/templates/builtins/

length

{{content | length}}
  • ๊ธธ์ด ํ™•์ธํ•˜๊ธฐ

truncatechars:num

{{content|truncatechars:10}}
  • 10์ž๋งŒ ์งค๋ผ์„œ ๋ณด์ด๊ธฐ

dictsort

{{ value|dictsort:"name" }}
  • dictionary ์ž๋ฃŒํ˜•์ผ๋•Œ, ๋ช…์‹œํ•œ key๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ

Template ํ™•์žฅ

pages/templates/base.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Django Basics - Pages</title>
    {% block css %}
    {% endblock %}
</head>
<body>
    <h1> Django Basic Syntax</h1>
    {% block body %}

    {% endblock %}
</body>
</html>

posts.html

{% extends 'base.html' %}

{% block css %}
<style>

    h1 {
        color: blue;
    }
</style>

{% endblock %}


{% block body %}
    <!-- {# Template language ์—์„œ์˜ ์ฃผ์„ #} -->
    <h1> Post No. {{id}}</h1>
    <p> {{content}}</p>
    <p> {{content | length}}</p>
    <p> {{content|truncatechars:10}}</p>
    <hr>
    {% for reply in replies %}
        <p> {{forloop.counter}} {{reply}}</p>
    {% endfor %}

    <hr>

    {% for reply in no_replies %}
        <p> {{forloop.counter}} {{reply}}</p>
        {% empty %}
        <p> There's no reply ใ… _ใ… </p>
    {% endfor %}
    <hr>
    {% if user == 'admin' %}
        <p> Accessible</p>
    {% else %}
        <p> Inaccessible</p>
    {% endif %}

{% endblock %}

Template ์„ค์ • - DIR

TEMPLATES = [
    {    
        # DTL ์—”์ง„์„ ํ™œ์šฉ. jinja2 ๋“ฑ์œผ๋กœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•จ
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # APP ๋‚ด์— ์žˆ๋Š” ํด๋”๊ฐ€ ์•„๋‹Œ ์ถ”๊ฐ€์ ์œผ๋กœ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ํ™œ์šฉํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ๋กœ.
        'DIRS': [os.path.join(BASE_DIR, 'intro', 'templates')],
        # APP_DIRS: True ์ธ๊ฒฝ์šฐ, ๋“ฑ๋ก๋œ app(INSTALLED_APPS)์˜ ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ๋Š” templates ํด๋”๋ฅผ ํ…œํ”Œ๋ฆฟ ํด๋”๋กœ ํ™œ์šฉํ•˜๊ฒ ๋‹ค.
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

BASE_DIR

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  • Linux, Windows ๋“ฑ OS์— ์ƒ๊ด€์—†์ด ์„ค์ •ํ•˜๋ ค๊ณ  os.path.dirname()์œผ๋กœ ํ•จ

DIRS ๋ฆฌ์ŠคํŠธ์— ๊ฒฝ๋กœ ์ •์˜ ํด๋” ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•˜๊ธฐ

00_django_intro/ <- BASE_DIR
    django_intro/
        templates/

Multiple Apps

<br

์•ž์œผ๋กœ๋Š” ํ•ญ์ƒ app์„ ์ƒ์„ฑํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํด๋” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง„๋‹ค.

app1/
    templates/
        app1/
            index.html
            a.thml
    urls.py
    views.py
    ...

app2/
    templates/
        app2/
            index.html
            b.thml
    urls.py
    views.py
    ...

1. url ์„ค์ • ๋ถ„๋ฆฌ

๊ฐ๊ฐ์˜ app ๋ณ„๋กœ url์„ ๊ด€๋ฆฌํ•œ๋‹ค.

  • ํ”„๋กœ์ ํŠธ ํด๋” urls.py ์ •์˜

    # django_intro/urls.py
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('pages/', include('pages.urls')),
        path('boards/', include('boards.urls')),
    ]
  • ๊ฐ ํ”„๋กœ์ ํŠธ๋ณ„ urls.py ์ •์˜

    from django.urls import path
    from . import views
    
    urlpatterns = [
        # /boards/
        path('', views.index),
        # /boards/new/
        path('new/', views.new),
        # /boards/complete/
        path('complete/', views.complete),
    ]

2. templates ํด๋” ๊ตฌ์กฐ

  • template ํŒŒ์ผ์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ django๋Š” ์•„๋ž˜์˜ ํด๋”๋“ค์„ ํƒ์ƒ‰ํ•œ๋‹ค.

    • DIRS ์— ์ •์˜๋œ ๊ฒฝ๋กœ์˜ ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ

    • NSTALLED_APPS ๋””๋ ‰ํ† ๋ฆฌ์˜ templates ํด๋”์˜ ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ ํƒ์ƒ‰

  • ์ด ๊ณผ์ •์—์„œ ์ค‘๋ณต๋œ ํŒŒ์ผ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋‹ค.

  • ๋”ฐ๋ผ์„œ, ์•ž์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.

app1/
    templates/
        app1/
app2/
    templates/
        app2/

Form ์„ ํ†ตํ•œ Request ์ฒ˜๋ฆฌ

  1. ์‚ฌ์šฉ์ž๋“ค๋กœ๋ถ€ํ„ฐ ๊ฐ’์„ ๋ฐ›์•„์„œ (boards/new/)

  2. ๋‹จ์ˆœ ์ถœ๋ ฅํ•˜๋Š” page ๊ตฌ์„ฑ (boards/complete/)

1. ์‚ฌ์šฉ์ž์—๊ฒŒ form ์–‘์‹ ์ œ๊ณต

1-1 url ์ง€์ •

# boards/urls.py
path('new/', views.new),

1-2 view ํ•จ์ˆ˜ ์ƒ์„ฑ

#boards/views.py
def new (request):
    return render(request, 'boards/new.html')

1-3 template

<form action="/boards/complete/">
    Title: <input type="text" name="title">
</form>
  • form tag์—๋Š” action ์†์„ฑ์„ ์ •์˜ํ•œ๋‹ค

    • ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋‚ด์š”์„ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” url

  • input tag์—๋Š” name ์†์„ฑ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋‚ด์šฉ์„ ๋‹ด์„ ๋ณ€์ˆ˜ ์ด๋ฆ„์„ ์ง€์ •ํ•œ๋‹ค

  • url ์˜ˆ์‹œ

    • /boards/complete/?title="์ œ๋ชฉ์ œ๋ชฉ"

2. ์‚ฌ์šฉ์ž ์š”์ฒญ ์ฒ˜๋ฆฌ

2-1. urls.py ์ •์˜

bords/url.py

path('/boards/complete', views.complete)

2-2. views.py

boards/views.py

def complete(request):
    title = request.GET.get('title')
    context = {
        'title': title
    }
    return render(request, 'boards/complete.html', context)
  • request์—๋Š” ์š”์ฒญ๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด๋“ค์ด ๋‹ด๊ธด object๊ฐ€ ์ €์žฅ๋˜์–ด ์žˆ๋‹ค

2-3. template

<!-- boards/templates/boards/complete.html -->
{{ title }}

+

Tip) project ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ!

$ cd intro/
$ django-admin startproject intro .

Last updated