AI 부트캠프/챕터4(12.05~12.27)

TIL 64

musukie 2024. 12. 17. 08:37

Django Template System

우리는 저번에 Template에 대해 배웠다. 다시 간단히 정리해보자. Django에서의 Template은 데이터를 보여주는 로직을 작성하는 부분, 즉 화면과 관련된 곳이다. Template의 기본 경로는 app_name/templates다.

 

우리는 이제 단순히 html뿐만 아니라, 데이터를 반영해서 화면을 보여줄 것이다. 이 때 Django의 Template System을 사용한다. Template System에서는 데이터를 표현하기 위한 다양한 도구를 제공한다.

 

※ 주의!

Django Template 안에 python 코드를 적으면 동작하지 않는다. Django Template은 python이 동작하는 곳이 아닌, Django Template Language(DTL)가 동작하는 곳이기 때문이다. 이를 통해 우리는 데이터를 표현할 수 있게 된다.

 

DTL 문법은 크게 변수, 필터, 태그, 주석 4가지로 분류된다. 하나하나 살펴보자.

변수 (Variable)

변수의 기본 형태는 아래와 같다.

{{ variable }}

중괄호 두 개 사이에 내가 넣고 싶은 변수를 넣어주면 된다. 이 변수는 View의 Context에서 넘겨준 데이터를 변수로 접근하는 것이다. View와 Template은 서로 왔다갔다 하는데, View에서 Template으로 넘길 때 (이 행위는 render() 함수의 세 번째 인자인)Context(dict형태로 넘겨진 데이터)라는 이름으로 data(View에서 여러 작업을 거친 후 화면에 보여줘야 할 데이터)를 넘겨준다. 그러면 Template에서는 이 데이터를 받아서 html 파일 안에 넣어줘야 한다. html 파일 안에 데이터를 넣을 때, 이 데이터에 접근하는 방법이 바로 변수다. 변수는 dict의 key값이다. 변수에 key값을 적으면, 나중에 html 파일에서는 Django DTL을 해석해서 value값을 보여주게 되는 것이다. . 연산자를 사용해서 변수 안쪽의 속성값들에 접근할 수 있다.

필터 (Filters)

변수와 형태가 비슷하지만, 변수에 버티컬바( | )를 넣는다.

{{ variable|filter }}

Django에는 약 60개의 built-in template filter가 제공된다. filter는 변수에 어떠한 작업을 추가적으로 더해서 보여지는 방법을 바꾸는 것이다. 예를 들어 'Jenny'라는 데이터가 들어왔을 때, 소문자로만 보여주고 싶다면 'jenny'라고 보여지게 해야 할 것이다. 이렇게 변수로 가져온 값을 살짝 변형시킬 때 filter를 적용한다.

 

공식문서에 들어가면 다양한 필터들을 확인할 수 있다. 어떤 filter들은 인자를 받기도 한다. {{변수|필터:"이 필터가 필요한 인자들"}}

또 커스텀 필터를 만들 수도 있다.

태그 (Tags)

태그의 기본 형태는 아래와 같다.

{% tag %}

반복문, 논리, 조건문 등을 써서 제어 흐름을 조절하거나 특수한 기능을 수행할 수 있게 한다. 예를 들어, 학생이면 <div> 태그를 '학생입니다.'를 보여주고, 선생님이면 <p> 태그 '선생님입니다.'를 보여주게 하는 것이다.

 

일부 태그는 시작 태그와 종료 태그가 있다. 예를 들면 아래의 if문이 있다.

{% if ~ %}
{% endif %}

주석 (Comments)

태그를 이용해서 주석을 달 수 있다.

{# 한 줄 주석 #}

{% comment %}
 여러줄
 주석
{% endcomment %}

실습

/hello로 들어오면 아래와 같은 화면이 나오게 하는 데까지는 어제 실습해봤다. 이제 여기서 화면의 Jenny를 다른 이름으로 바꿔보자. html 파일을 수정하는 게 아닌, 오늘 배운 데이터를 받아서 동적으로 수정되게 해보는 것이다.

즉, Context를 넘기는 것, 이 Template에서 사용할 어떠한 데이터를, View에서 Context에 담아서 data를 Template에 넘겨주는 것이다. 그리고 나서 오늘 배운 DTL을 사용해서 한번 넘겨준 data를 보여줘 볼 것이다.

 

우선은 my_first_pjt 폴더의 우리가 만든 앱인 articles 폴더의 views.py 파일로 가자. 여기서 우리는 배우는 중이니 헷갈리지 않게 변수 이름을 context 변수로 담아서 갈 것이다.

def hello(request):
    context = {
        "name":"Minho",
    }
    return render(request, "hello.html", context)

context를 dict 형태로 넣어주고, render() 함수에 3번째 인자로 변수 context를 넣어주었다. View에서 데이터를 담았으니, Template에 context로 넘겨줄 것이다.

 

넘겨준 데이터를 받아서, 받은 데이터를 보여줄 부분에 넣어주어야 한다. articles 폴더의 hello.html 파일로 넘어가자.

이제 여기서 Template 변수를 사용한다. 즉, DTL을 써주는 것이다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Hello, {{name}}!</h1>
</body>
</html>

우리는 context의 dict에서 name이라는 key값으로 접근해서, 안에 들어있는 Minho라는 데이터를  html에서 보여주게 될 것이다.

 

아까 켜두었던 서버를 새로고침하면 아래와 같이 화면이 바뀐 것을 확인할 수 있다.

정리해보자.

View에서 데이터를 Context에 담아서 render() 함수의 3번째 인자로 넣어주고, 이를 Template에서 넘겨받아서, cotext의 ditc의 key값을 통해 데이터(value)에 접근할 수 있게 되는 것이다.

 

더 많은 데이터를 넘겨줄 수도 있다. context에 넘겨줄 데이터를 더 추가하고, html 파일에 데이터를 넘겨받을 변수들을 추가하면된다.

def hello(request):
    name = "Minho"
    tags = ["python", "django", "html", "css"]
    books = ["해변의 카프카", "코스모스", "백설공주", "어린왕자"]

    context = {
        "name":name,
        "tags":tags,
        "books":books,
    }
    return render(request, "hello.html", context)

이렇게 views.py에 변수들을 추가해주었다. 여러 개의 데이터를 한번에 넘기는 tags와 books도 있다. html 파일에서 tags와 books를 다 보여주는 것이 아니라, 하나 씩만 보여주고 싶을 때, . 연산자를 사용하는 것이다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Hello, {{name}}!</h1>
    <p> 첫 번째 태그는 {{tags.0}} </p>
</body>
</html>

위의 코드처럼 {{tags.0}}으로 . 연산자를 사용해 tags의 첫 번째인 python만 보여지게 된다. 파이썬 문법이 아니기 때문에 tags[0]이라고 쓰면 안 된다.

 

이제 여기에 필터를 적용해보자. 다 대문자로 보여지게 해볼 것이다. 필터를 추가해보자.

<p> 첫 번째 태그는 {{tags.0|upper}} </p>

그러면 아래와 같은 화면이 보여지게 된다.

이제 책 목록 전체가 다 보여지게 할 것이다. 이 때 for문을 사용하기 위해서 태그(tags)를 사용한다. 파이썬의 for문과 비슷하나 다르다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Hello, {{name}}!</h1>
    <p> 첫 번째 태그는 {{tags.0|upper}} </p>
    <p> 모든 책 목록</p>
    <ul>
        {% for book in books %}
        <li>{{book}}</li>
        {% endfor %}
    </ul>
</body>
</html>

그 후 새로고침하면 화면이 아래와 같이 나타난다.

Template Inheritance

지금까지 만든 html 파일들을 보면, body 태그 안의 내용 빼고는 다 같은 코드임을 확인할 수 있다. 우리는 이제 class로 따지면 '상속'을 하고 싶어졌다. 같은 부분은 상속받아오고, 다른 부분만 수정하고 싶은 것이다. 이 때 Template Inheritance를 사용하는 것이다. Django는 Template 상속을 지원한다.

 

공통되는 부분은 상위 template에 정의해놓고, 이 상위 Template에 구멍을 뚫어놓는다. 하위 템플릿은 이를 상속받아서, 다르게 작성할 부분만 작성하면 된다. 다르게 작성할 부분을 상위 템플릿에 명시하는 것을 블록(block)이라고 한다. 이런 형태를 스켈레톤 형태라고 한다.

 

이 때 우리는 2가지 태그를 기억하면 된다.

첫 번째로, 우리가 상위 템플릿에 구멍을 뚫어야 하니까 block 태그가 있다. 문법은 아래와 같다.

{% block block_name %} {% endblock block_name %}

블록은 여러 개를 뚫을 수도 있기 때문에, 각각의 블록에 block_name을 지정할 수 있다. 여는 태그와 닫는 태그로 구성돼있다.

 

두 번째는 하위 템플릿에서 상위 템플릿상속받아 오는 태그다.

{% extends 'template_name' %}

이 태그는 반드시 템플릿의 가장 위에 위치해야 한다. 다중 상속은 지원하지 않는다. A 템플릿과 B 템플릿을 모두 상속받을 수 없다는 것이다. A를 상속받아서 B를 만들고, B를 상속받아서 C를 만드는 것은 가능하다.

실습

부모 템플릿을 만들어준다. 보통 base.html이라는 이름으로 파일을 만든다. 중복되는 부분을 다 작성해주고 구멍을 뚫어준다. 우리는 body 태그의 내용이 중복되므로 여기에 block 태그를 작성한다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    {% block content %}
    {% endblock content %}
</body>
</html>

endblock은 이름을 명시해주지 않고 {%endblock%}이라고만 써도 되지만, 가독성을 위해 이름을 적어준다.

 

이제 이를 상속받는 하위 템플릿을 작성해보자. 우리는 전에 작성했던 hello.html을 하위 템플릿으로 만들어볼 것이다. html 파일의 가장 위에 extends 태그를 작성해준다.

{% extends 'base.html' %}

{% block content %}
    <h1>Hello, {{name}}!</h1>
    <p> 첫 번째 태그는 {{tags.0|upper}} </p>
    <p> 모든 책 목록</p>
    <ul>
        {% for book in books %}
        <li>{{book}}</li>
        {% endfor %}
    </ul>
{% endblock content %}

상속받은 후에 달라질 부분을 작성해주어야 한다. 이 때 다시 block 태그를 사용한다. 중복되는 부분은 다 지워주면 된다.

 

html은 들여쓰기 문법이 아니기 때문에 들여쓰기 정리를 해주지 않아도 되지만, 보기 좋으라고 들여쓰기를 해주었다.

Template 참조 위치

하나의 프로젝트에는 여러 개의 앱이 있을 수 있다. 우리가 다른 앱도 만든다면, 모든 앱에서 base.html을 상속받게 하고 싶다. 그러면 이 base.html을 가장 최상위의 폴더로 옮겨야 한다.(지금은 우리가 만들었던 앱인 article 폴더 안에 base.html 파일이 있다.)

 

가장 최상위에 폴더를 하나 만들자. 여기가 모든 앱들이 공통적으로 가져야 할 Template들이 들어있는 폴더로 쓰일 것이다. 이름 아무거나 지어도 되는데 지금은 templates라고 지어주었다. 이제 article 폴더 안에 있던 base.html 파일을 templates 폴더로 옮겨준다.

 

이제 커스텀으로 지정한 템플릿들의 경로를 지정해주어야 한다. my_first_pjt 폴더 안의 settings.py의 59번째 줄을 수정하면 된다. 여기가 Django에게 각각의 앱들에서 templates라는 폴더에서 html 파일을 찾도록 지정해준 부분이다. 우리는 커스텀으로 지정한 템플릿 경로를 지정하기 위해서는 'DIRS'를 작성해주면 된다.

'DIRS': [BASE_DIR / "templates"],

베이스 디렉토리 아래에 있는 "templates" 폴더에서 html 파일을 찾게 지정했다. 여기서 BASE_DIR은 settings.py 파일의 16번째줄에 정의돼있다.

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

현재 이 파일의 부모의 부모 위치를 BASE_DIR로 정의해놓았다. 즉, 현재 파일은 settings.py의 부모인 my_first_pjt 폴더의 부모인 가장 최상단의 경로(여기서는 MY_FIRST_PJT 폴더다.)를 의미하는 것이다. Django가 알아서, 개발자들이 많이 쓰는 위치기 때문에, BASE_DIR을 정의해준 것이다. 파이썬 문법(os.path)을 써도 되고, 문자열로 경로를 직접 작성해줘도 되지만, Django에서 지원해주니까 편하게 쓰면 된다.

'AI 부트캠프 > 챕터4(12.05~12.27)' 카테고리의 다른 글

TIL 70  (0) 2024.12.26
TIL 65  (2) 2024.12.18
TIL 63  (0) 2024.12.16
TIL 62  (1) 2024.12.16
WIL 10  (1) 2024.12.13