[day-34] 템플릿 상속

Joohyung Park·2024년 2월 25일
0

[모두연] 오름캠프

목록 보기
63/95

템플릿 상속?

웹 애플리케이션에서 HTML 구조를 재사용하게 해주는 기능이다. 공통적인 HTML 구조를 기본 템플릿에 정의하고, 각 페이지에서 이를 상속받아 사용한다.

기본 템플릿에서는 {% block %} 태그를 사용해 자식 템플릿에서 재정의할 수 있는 영역을 지정한다. 이런 방식으로 웹사이트의 일관성을 유지하면서도 각 페이지를 개별적으로 개발할 수 있다. 공통 요소의 변경이 필요할 때는 기본 템플릿만 수정하면 된다.

기본 세팅

pip install django
django-admin startproject tutorialdjango .
python manage.py migrate

python manage.py startapp main
python manage.py startapp blog
프로젝트명 > settings.py

ALLOWED_HOSTS = ["*"]

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "추가한 앱 이름",
]

URL 구조 작성

''
'about/'
'contact/'
'blog/'
'blog/<int:pk>/'

앱이름: main
URL             views 함수이름	 html 파일이름	    비고
''              index           index.html
'about/'        about
'contact/'      contact

앱이름: blog
URL             views 함수이름   html 파일이름      비고
'blog/'         blog            blog.html	
'blog/<int:pk>' post            post.html          게시물이 없을 경우에는 404로 연결

urls.py, views.py

기본 프로젝트의 urls.py와 각 앱마다 urls.py를 정의하고 views.py에서 urlpatterns의 함수들을 정의한다.

main > urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="index"),
    path("about/", views.about, name="about"),
    path("contact/", views.contact, name="contact"),
]

템플릿에서 name의 값으로 접근 가능하다.

blog > urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("", views.blog_list, name="blog_list"),
    path("<int:pk>/", views.blog_detail, name="blog_detail"),
]
blog > views.py
from django.shortcuts import render

blog_database = [
    {
        "id": 1,
        "title": "제목1",
        "content": "내용1",
        "created_at": "2021-02-22",
        "updated_at": "2021-02-22",
        "author": "홍길동",
        "category": "일상",
        "tag": ["태그1", "태그2"],
        "view_count": 0,
        "thumbnail": "https://picsum.photos/200/300",
        "like_count": 3,
        "like_user": [10, 20, 21],
    },
    {
        "id": 2,
        "title": "제목2",
        "content": "내용2",
        "created_at": "2021-02-23",
        "updated_at": "2021-02-23",
        "author": "김철수",
        "category": "일기",
        "tag": ["태그1", "태그3"],
        "view_count": 0,
        "thumbnail": "https://picsum.photos/200/300",
        "like_count": 10,
        "like_user": [10, 20, 21, 22, 23, 24, 25, 26, 27, 28],
    },
    {
        "id": 3,
        "title": "제목3",
        "content": "내용3",
        "created_at": "2021-02-24",
        "updated_at": "2021-02-24",
        "author": "이영희",
        "category": "맛집",
        "tag": ["태그1", "태그3"],
        "view_count": 0,
        "thumbnail": "https://picsum.photos/200/300",
        "like_count": 20,
        "like_user": [10, 20, 21, 22, 23, 24, 25, 26, 27, 28],
    },
    {
        "id": 4,
        "title": "제목4",
        "content": "내용4",
        "created_at": "2021-02-25",
        "updated_at": "2021-02-25",
        "author": "박민수",
        "category": "여행",
        "tag": ["태그1", "태그3"],
        "view_count": 0,
        "thumbnail": "https://picsum.photos/200/300",
        "like_count": 30,
        "like_user": [10, 20, 21, 22, 23, 24, 25, 26, 27, 28],
    },
]


def blog_list(request):
    context = {"blog_list": blog_database}
    return render(request, "blog/blog_list.html", context)


def blog_detail(request, pk):
    context = {"blog": blog_database[pk - 1]}
    return render(request, "blog/blog_detail.html", context)

render

  • render(request, html파일, context(딕셔너리 형태)
  • html 파일을 일반 텍스트로 가져오며, 중괄호와 같은 문법이 나오면 context에 있는 값을 가져와 넣어줌
  • 넘겨줄 때에는 HTTPResponse를 사용
  • request : 사용자가 보내는 요청에 대한 정보(로그인 정보 등)

템플릿 태그

  • 템플릿 내에서 파이썬 코드를 실행하거나, 템플릿에 로직 추가 가능
  • {{ variable }} : 렌더링 시 해당 변수의 값으로 치환
  • {% for %} {% endfor %}
  • {{name|lower}} : name의 값을 소문자로 변환하여 출력 등

부모코드(상속하는 코드)

# 상속해주는 부분(수정할 특정 부분)에 다음과 같이 선언
{% block 자식이름 %}
{% endblock %}

자식코드(상속받는 코드)

{% extends '부모html파일명' %}
# 부모의 대부분의 내용을 상속받고 해당 부분만 수정하겠다!
{% block 자식이름 %}
... 실제 사용할 자식 코드 ...
{% endblock %}

부모코드 예시

# templates > base > base.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>weniv blog</title>
</head>
<body>
    <header>
        <h1>weniv blog</h1>
        <nav>
            <ul>
                <li>메뉴1</li>
                <li>메뉴2</li>
                <li>메뉴3</li>
            </ul>
        </nav>
    </header>

    <main>
        {% block contents %}
        <p>test 이어서 써집니다1</p>
        <p>test 이어서 써집니다2</p>
        {% endblock %}
    </main>

    <footer>
        <p>저작권은 weniv에게 있습니다.</p>
    </footer>
</body>
</html>

자식코드 예시

# templates > blog > blog_list.html

{% extends 'base/base.html '%}

{% block contents %}
<h1>bloglist</h1>
<ul>
    {% for blog in blog_list %}
    <li>
        {{ forloop.counter }}
        <a href="{% url 'blog_detail' blog.id %}">{{ blog.title }}</a>
    </li>
    {% endfor %}
</ul>
{% endblock %}

extends라는 선언으로 부모의 html을 상속받고 있으며, % block contents %로 수정할 부분을 정의하고 있다.

해당 부분을 제외한 부분은 부모를 그대로 따라간다.

여기서 block뒤에오는 contentsblock 이름으로, 다른 이름이 들어가도 상관없다.

{{ forloop.counter }} 부분은 현재 반복문이 몇 번째 루프인지를 나타낸다. 첫 번째 루프에서는 1을 반환하는 그런 거라고 생각하면 된다.

profile
익숙해지기 위해 기록합니다

0개의 댓글