-
Notifications
You must be signed in to change notification settings - Fork 0
12 Template Inheritance & Template Loader
여러 템플릿 파일 별로 필연적으로 발생하는 중복을 상속을 통해 중복 제거
상속은 여러 번 이뤄질 수 있음
부모 템플릿은 전체 레이아웃을 정의하며, 자식 템플릿이 재정의할 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/>
© 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/>
© 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/>
© 2017. AskDjango
</body>
</html>
- 프로젝트 전반적인 레이아웃 템플릿 : 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경로를 알려줘야함.
다수 디렉토리 목록에서 지정 상대경로를 가지는 템플릿을 찾음
- 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)
settings.INSTALLED_APPS에 설정된 앱 디렉토리 내 templates 경로에서 템플릿 파일을 찾음 앱 디렉토리 별로 각 앱을 위한 템플릿 파일을 위치
- blog앱용 템플릿은 blog/templates/ 경로에 두는 것이 관리성 좋음
- shop앱용 템플릿은 shop/templates/ 경로에 두는 것이 관리서 좋음
프로젝트 전반적으로 쓰일 템플릿 파일은 "특정앱/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 경로로 찾습니다.
``