jinja

[template] Jinja - 템플릿 - 템플릿 상속 ★★★ (Template - Template Inheritance)

목차
  1. 기본 템플릿 (Base Template)
  2. 자식 템플릿 (Child Template)
  3. 슈퍼 블럭 (Super Blocks)
  4. 중접 확장 (Nesting extends)
  5. 명명된 블록 종료 태그 (Named Block End-Tags)
  6. 블록 중첩 및 범위 (Block Nesting and Scope)
  7. 필수 블록 (Required Blocks)
  8. 템플릿 객체 (Template Objects)

 

기본 템플릿 (Base Template)

 

  • 기본템플릿(Base Template)은 base.html 파일명 갖으며 HTML 기본 뼈대를 정의함.
  • 자식템플릿(Child Templates)은 기본템플릿의 빈 블록들을 콘텐츠로 채우는 역할 함.

 


[예제]

 

<!DOCTYPE html>

<html lang="en">

<head>

    {% block head %}

    <link rel="stylesheet" href="style.css" />

    <title>{% block title %}{% endblock %} - My Webpage</title>

    {% endblock %}

</head>

<body>

    <div id="content">{% block content %}{% endblock %}</div>

    <div id="footer">

        {% block footer %}

        &copy; Copyright 2012 by <a href="http://homzzang.com/">홈짱닷컴</a>.

        {% endblock %}

    </div>

</body>

</html>

 


PS. 코드 해설

 

  • 위 예에서 {% block %} 태그는 자식템플릿이 채울 수 있는 4개의 블록을 정의함. block 태그 역할은 자식템플릿이 템플릿의 해당 자리 표시자를 재정의할 수 있음을 템플릿 엔진에 알리는 것뿐임
  • 블록 태그는 if와 같은 다른 블록 안에 있을 수 있지만 if 블록이 실제로 렌더링되는지 여부에 관계없이 항상 실행됨.

 

 

자식 템플릿 (Child Template)

[예제]

 

{% extends "base.html" %}

{% block title %}Index{% endblock %}

{% block head %}

    {{ super() }}

    <style type="text/css">

        .important { color: blue; }

    </style>

{% endblock %}

{% block content %}

    <h1>Index</h1>

    <p class="important">

      Welcome to Homzzang.com

    </p>

{% endblock %}

 


 

1.

  • {% extends %} 부분이 핵심인데, 이는 템플릿 엔진에게 이 템플릿이 다른 템플릿을 확장(=상속)함을 알림. 즉, 템플릿엔진이 이 템플릿 평가 시 먼저 부모 템플릿을 찾음.
  • extends 태그는 템플릿의 첫 번째 태그여야 함. 이 태그 앞에 뭔가 있을 경우 정상적으로 로드 되어 혼란 야기할 수 있음.
  • 이 동작과 이를 활용하는 방법에 대한 자세한 내용은 Null-Default Fallback을 참조. 
  • 또한 블록은 주변 조건이 참인지 거짓인지에 관계없이 항상 채워짐.

 

2.

템플릿의 파일 이름은 템플릿 로더에 좌우됨. 예를 들어, FileSystemLoader 사용하면 파일 이름을 제공하여 다른 템플릿에 접근 가능. 슬래시 사용해 하위 디렉터리의 템플릿에 접근 가능.

 

{% extends "layout/default.html" %}

 

그러나 이 동작은 Jinja를 포함하는 애플리케이션에 따라 달라질 수 있음. 자식 템플릿은 footer 블록을 정의하지 않으므로 부모 템플릿의 값이 대신 사용됨.

 

3.

  • 동일한 템플릿에서 동일한 이름을 가진 여러 개의 {% block %} 태그를 정의할 수 없음. (∵ block 태그가 "양쪽" 방향으로 작동하기 때문임. 즉, block 태그는 자리 표시자 역할 뿐만 아니라 부모의 자리 표시자를 채우는 콘텐츠도 정의함. 템플릿에 비슷한 이름의 {% block %} 태그가 두 개 있는 경우 해당 템플릿의 부모는 블록의 콘텐츠 중 어떤 것을 사용할지 알 수 없음.)
  • 단, self 변수로 해당 블록을 여러 번 호출해 출력 가능.


<title>{% block title %}{% endblock %}</title>

<h1>{{ self.title() }}</h1>

{% block body %}{% endblock %}

 

 

슈퍼 블럭 (Super Blocks)

※ super() 호출하면 부모 블록의 내용을 렌더링 가능.

 

{% block sidebar %}

    <h3>Table Of Contents</h3>

    ...

    {{ super() }}

{% endblock %}

 

 

중접 확장 (Nesting extends)

※ {% extenses %} 수준이 중첩적일 때, 바로 위 부모 템플릿을 건너뛰고 그 보다 상위 템플릿을 상속해야 할 경우 super.super() 같이 체인화.

 

# parent.tmpl

body: {% block body %}Hi from parent.{% endblock %}


# child.tmpl

{% extends "parent.tmpl" %}

{% block body %}Hi from child. {{ super() }}{% endblock %}

{# 렌더링 결과: Hi from child. Hi from parent. #}

 

# grandchild1.tmpl

{% extends "child.tmpl" %}

{% block body %}Hi from grandchild1.{% endblock %}

{# 렌더링 결과: Hi from grandchild1. #}

 

# grandchild2.tmpl

{% extends "child.tmpl" %}

{% block body %}Hi from grandchild2. {{ super.super() }} {% endblock %}

{# 렌더링 결과: Hi from grandchild2. Hi from parent. #}

 


명명된 블록 종료 태그 (Named Block End-Tags)

※ 가독성 ↑

 

{% block sidebar %}

    {% block inner_sidebar %}

        ...

    {% endblock inner_sidebar %}

{% endblock sidebar %}

 

PS. endblock 태그 뒤 이름은 block 태그 뒤 이름과 일치해야 함.

 

블록 중첩 및 범위 (Block Nesting and Scope)

 

1. 

블록은 더 복잡한 레이아웃을 위해 중첩될 수 있음. 그러나 기본적으로 블록은 외부 범위의 변수에 접근 못 함.


{% for item in seq %}

    <li>{% block loop_item %}{{ item }}{% endblock %}</li>

{% endfor %}

 

위 예제 경우, 블록 내에서 item을 사용할 수 없기 때문에 빈 <li> 아이템들을 출력함. 그 이유는 블록이 하위 템플릿으로 대체되면 블록에 정의되지 않았거나 컨텍스트에 전달된 변수가 나타날 수 있기 때문임.

 

2. 

Jinja 2.2부터 블록 선언에 scoped 수정자 추가해 블록을 "scoped"로 설정해 블록에서 외부범위의 변수를 사용 가능할 수 있음을 명시적으로 지정 가능.

 

{% for item in seq %}

    <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>

{% endfor %}

 

3.

블록을 재정의할 때 scoped 수정자를 제공할 필요가 없음.

 

 

필수 블록 (Required Blocks)

 

1.

블록에 required 수정자 추가 가능함. 블록은 어느 시점에선 재정의되어야 하나, 반드시 직계 하위 템플릿에 의해 재정의될 필요는 없음. required 블록에는 공백과 주석만 포함될 수 있으며 직접 렌더링할 수 없음.

 

page.txt

{% block body required %}{% endblock %}

 

issue.txt

{% extends "page.txt" %}

 

bug_report.txt

{% extends "issue.txt" %}

{% block body %}버스 시연 단계 제공.{% endblock %}

 

page.txt 또는 issue.txt 렌더링하면 body 블록을 재정의 안 해서 TemplateRuntimeError 발생함. bug_report.txt 렌더링은 블록을 재정의하므로 성공함.

 

2.

scoped 수정자와 함께 사용 시 반드시 required 수정자는 scoped 수정자 뒤에 와야 함. (아래는 유효한 몇 가지 예임.)

{% block body scoped %}{% endblock %}

{% block body required %}{% endblock %}

{% block body scoped required %}{% endblock %}

 

 

템플릿 객체 (Template Objects)

 

extends, include, import 는 로드할 템플릿 이름 대신 템플릿 객체 사용 가능함. Python 코드 사용해 템플릿을 먼저 로드하고 이를 렌더링에 전달할 수 있으므로 이는 일부 고급 상황에서 유용할 수 있음.

 

if debug_mode:

    layout = env.get_template("debug_layout.html")

else:

    layout = env.get_template("layout.html")


user_detail = env.get_template("user/detail.html")

return user_detail.render(layout=layout)

 

{% extends layout %}

 

PS. 위 파란색 코드 경우, extends가 문자열 대신 템플릿 객체 변수 이용해 렌더링 함에 주목. 



분류 제목
intro Jinja - 소개 - 설치
api Jinja - API - 기초
api Jinja - API - 고급 API
api Jinja - API - 자동 이스케이프
api Jinja - API - 식별자에 관한 참고 사항
api Jinja - API - 정의되지 않은 유형
api Jinja - API - 문맥
api Jinja - API - 로더
api Jinja - API - 바이트코드 캐시
api Jinja - API - 비동기 지원
api Jinja - API - 정책
api Jinja - API - 유용
api Jinja - API - 예외
api Jinja - API - 맞춤 필터
1/11
목록
 홈  PC버전 로그인 일본어
그누앞단언어
그누뒷단언어
그외코딩언어
그누보드
제작의뢰
Q&A
커뮤니티 2
웹유틸
회원센터
홈짱닷컴 PC버전 로그인