Skip to content

12 Template Inheritance & Template Loader

YeongBaeeee edited this page Apr 20, 2017 · 2 revisions

Template Inheritance

여러 템플릿 파일 별로 필연적으로 발생하는 중복을 상속을 통해 중복 제거
상속은 여러 번 이뤄질 수 있음
부모 템플릿은 전체 레이아웃을 정의하며, 자식 템플릿이 재정의할 block을 다수 정의해야 함
자식 템플릿은 부모 템플릿을 상속받은 후에 부모 템플릿의 block 영역에대해 재정의만 가능하며 그 외 코드는 무시
템플릿 상속 문법 : 항시 자식템플릿 코드 내, 최상단에 쓰여져야함.

{% extends "부모템플릿경로" %}

상속을 쓰기 전

blog/templates/blog/post_list.html ////으로 중복영역 표시

///////////////////////////////////////////
<!doctype html>
<html>
<head>
 <meta charset="utf-8" />
 <title>AskDjango Blog</title>
</head>
<body>
 <h1>AskDjango Blog</h1>
///////////////////////////////////////////
 {% for post in post_list %}
 <a href="{% url "blog:post_detail" post.id %}">{{ post.title }}</a>
 {% endfor %}
///////////////////////////////////////////
 <hr/>
 &copy; 2017. AskDjango
</body>
</html>
///////////////////////////////////////////

blog/templates/blog/post_detail.html

///////////////////////////////////////////
<!doctype html>
<html>
<head>
 <meta charset="utf-8" />
 <title>AskDjango Blog</title>
</head>
<body>
 <h1>AskDjango Blog</h1>
///////////////////////////////////////////
 <h2>{{ post.title }}</h2>
 {% if post.image %}
 <img src="{{ post.image.url }}" />
 {% endif %}
 {{ post.content|linebreaks }}
///////////////////////////////////////////
 <hr/>
 &copy; 2017. AskDjango
</body>
</html>
///////////////////////////////////////////

상속을 쓰고 나면

blog/templates/blog/post_list.html

{% extends "blog/layout.html" %}
{% block content %}
 {% for post in post_list %}
 <a href="{% url "blog:post_detail" post.id %}">{{ post.title }}</a>
 {% endfor %}
{% endblock %}

blog/templates/blog/post_detail.html

{% extends "blog/layout.html" %}
{% block content %}
 <h2>{{ post.title }}</h2>
 {% if post.image %}
 <img src="{{ post.image.url }}" />
 {% endif %}
 {{ post.content|linebreaks }}
{% endblock %}

부모템플릿 작성법

blog/layout.html

<!doctype html> <html> <head>
<meta charset="utf-8" />
<title
>AskDjango Blog</title>
</head>
<body>

<h1>AskDjango Blog</h1>
 {% block content %}   
 {% endblock %}

<hr/>
 &copy; 2017. AskDjango
</body>
</html>

2단계의 상속을 추천

  • 프로젝트 전반적인 레이아웃 템플릿 : askdjango/templates/layout.html
    • 각 앱 별 레이아웃 템플릿 #1 : blog/templates/blog/layout.html
    • 각 템플릿 #1 : blog/templates/blog/post_list.html
    • 각 템플릿 #2 : blog/templates/blog/post_detail.html
    • 각 템플릿 #3 : blog/templates/blog/post_form.html
    • 각 앱 별 레이아웃 템플릿 #2 : shop/templates/shop/layout.html
    • 각 템플릿 #4 : shop/templates/shop/item_list.html
    • 각 템플릿 #5 : shop/templates/shop/item_detail.html
    • 각 템플릿 #6 : shop/templates/shop/item_order_form.html
      Template Loader에 대한 이해가 필요

templates/layout.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Django{% endblock %}</title>
</head>
<body>

<h1>Django Blog</h1>

{% block content %}
{% endblock %}

</body>
</html>

blog/templates/blog/layout.html

{% extends "layout.html" %}

{%  block titel %}Blog{% endblock %}

blog/templates/blog/post_list.html

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

{% block content %}
    <form action="" method="get">
    <input type="text" name="q" value="{{ q }}"/>
    <input type="submit" value="검색"/>
</form>

<ul>
{% for post in post_list %}
    <li>
        {{ post.id }}
        <a href ="/blog/{{ post.id }}">
            {{ post.title }}
        </a>
        <small>by {{ post.author }}</small>
        <small>at {{ post.updated_at }} </small>
    </li>
{% endfor %}
</ul>

<ul>
    <li>http://www.13.124.86.222:8000/blog/ 로 접속해보세요.</li>
</ul>
{%  endblock %}

요렇게~~~~!!!!!! 그리고 마지막으로 setting.py에 새로만든 templates경로를 알려줘야함.

Template Loader

다수 디렉토리 목록에서 지정 상대경로를 가지는 템플릿을 찾음

  • app_directories.Loader 와 filesystem.Loader
    위 Loader를 통해, 템플릿 디렉토리가 있을 후보 디렉토리 리스트를 작성
    이는 장고 서버 초기 시작시에만 1회 작성
    주로 아래 함수를 통해 Template 파일들을 활용합니다.
  • render : 템플릿을 렌더링은 문자열로 HttpResponse 객체를 리턴
  • render_to_string : 템플릿 렌더링한 문자열을 리턴

response = render(request, 'blog/post_list.html', context_params) welcome_message = render_to_string('accounts/signup_welcome.txt', context_params)

app_directories.Loader

settings.INSTALLED_APPS에 설정된 앱 디렉토리 내 templates 경로에서 템플릿 파일을 찾음 앱 디렉토리 별로 각 앱을 위한 템플릿 파일을 위치

  • blog앱용 템플릿은 blog/templates/ 경로에 두는 것이 관리성 좋음
  • shop앱용 템플릿은 shop/templates/ 경로에 두는 것이 관리서 좋음

filesystem.Loader

프로젝트 전반적으로 쓰일 템플릿 파일은 "특정앱/templates/" 경로가 아닌 별도의 경로에 저장이 필요
프로젝트/settings.py 에 후보지 디렉토리 경로 지정

TEMPLATES = [{
 # 중략
 'DIRS': [
 os.path.join(BASE_DIR, '프로젝트명'
, 'templates'),
 ],
 # 중략
}]

render 혹은 render_to_string 함수가 호출되면, 미리 작성된 템플릿 후보 디렉토리들을 차례대로 순회하며 템플릿 파일을 찾음
render(request, 'blog/post_list.html') 이 호출되면
blog/templates/blog/post_list.html 파일 체크, 없으면 다음
shop/templates/blog/post_list.html 파일 체크, 없으면 다음
diary/templates/blog/post_list.html 파일 체크, 없으면 다음
프로젝트명/templates/blog/post_list.html 파일 체크, 없으면 다음
마지막까지 검사해서 없을 경우, TemplateDoesNotExist 예외 발생
아래와 같이 템플릿파일을 생성하고

  • blog/templats/post_list.html
  • shop/templats/post_list.html 각 앱 내 뷰에서 render(request, 'post_list.html') 와 같이 쓴다면, blog/shop 앱 모두에서 항상 blog/templates/post_list.html 템플릿만이 사용될 것. 템플릿 경로가 모두 동일하기 때문
  • blog/templats/post_list.html : post_list.html 경로로 찾습니다.
  • shop/templats/post_list.html : post_list.html 경로로 찾습니다.
    템플릿 경로가 겹치지 않게 할려면,
  • 방법1) 항상 템플릿 파일을 생성할 때마다, 개발자가 템플릿 파일명이 중복되지 않는지 체크해서 생성한다.
  • 방법2) namespace 역할로서 앱 이름의 디렉토리를 중간에 둡니다.
  • 장고는 다른 앱이 같은 이름을 가지는 것을 허용하지 않습니다. 예시
> blog/templats/blog/post_list.html : blog/post_list.html 경로로 찾습니다.
> shop/templats/shop/post_list.html : shop/post_list.html 경로로 찾습니다.
``