Django

템플릿 서빙 방법 및 문법

Strickland 2024. 5. 5. 13:05

현재 폴더 구조 

 

장고/monthly_challenges/monthly_challenges/setting.py 수정 

.
.
.
.
INSTALLED_APPS = [
    'challenges', #여기 추가
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
.
.
.
.
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            BASE_DIR / "templates"
        ],
        'APP_DIRS': True,  #여기도 True 여야함 !!!!!!
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

위의 settings.py 파일에서 주석으로 표시 된 부분 설정!!

 

 

challlenges/urls.py 에서 다음과 같은 코드를 실행

from django.http import HttpResponse, HttpResponseNotFound, HttpResponseRedirect
from django.urls import reverse
from django.template.loader import render_to_string

def monthly_challenge(request, month):

  try:
    challenge_text = monthly_challenges[month]
    response_data = render_to_string("challenges/challenge.html")
    return HttpResponse(response_data)
  except:
    return HttpResponseNotFound("<h1>This month is not supported</h1>")

1. render_to_string 의 인자로 "challenges/challenge.html" 전달 

2. 위의 urls.py 는 challenges 폴더에 속해있음으로 challenges/templates 안에서 "challenges/challenge.html" 을  자동으로 검색함

3. 우리가 setting.py  의 INSTALLED_APPS 에 "challenges" 를 추가해주었기 때문에 가능한 일이다!

 

 

위의 코드를 아래로 축약 가능

from django.shortcuts import render
from django.http import HttpResponse, HttpResponseNotFound, HttpResponseRedirect
from django.urls import reverse

def monthly_challenge(request, month):
  try:
    challenge_text = monthly_challenges[month]
    return render(request, "challenges/challenge.html",{
      "text": challenge_text,
      "month_name": month.capitalize(),

    })
  except:
    return HttpResponseNotFound("<h1>This month is not supported</h1>")

 

render 는 request 와 템플릿 path, 그리고 뷰에 전달할 인자를 받는다 

 

challenges.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{ month_name }} Challenge</title>
</head>
<body>
    <h1>{{ month_name }} Challenge</h1>
    <h2>{{text}}</h2>
</body>
</html>

urls.py 에서 전달한 text와 month_name 을 다이나믹 렌더링으로 서빙한다.

 

 

 

for 태그 사용법

challenges/views 를 다음과 같이 수정

from django.shortcuts import render
from django.http import HttpResponse, HttpResponseNotFound, HttpResponseRedirect
from django.urls import reverse

def index(request):
  months = list(monthly_challenges.keys())

  return render(request, "challenges/index.html", {
    "months": months,
  })

 

render 의 세번쨰 인수로 "month" 배열을 넘겨줌 

 

index.html 은 다음과 같이 수정

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>All challenges</title>
</head>
<body>
    <ul>
        {% for month in months %}
            <li><a href="/challenges/{{month}}">{{ month|title}}</a></li>
        {% endfor %}

    </ul>

</body>
</html>

 

for 태그를 이용해 반복 렌더링

 

url 태그 사용법

우리는 이전에  challenges/urls.py 에서 "month-challenge" 라는 url 을 등록해두었다.

challenges/urls.py

from django.urls import path
from . import views

urlpatterns = [
  path('', views.index),
  path('<int:month>', views.monthly_challenge_by_number),
  path('<str:month>', views.monthly_challenge, name="month-challenge")

]

 

이 등록해둔 url 을 장고 html에서 꺼내서 쓸 수 있다.

index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>All challenges</title>
</head>
<body>
    <ul>
        {% for month in months %}
            <li><a href="{%  url 'month-challenge' month %}">{{ month|title}}</a></li>
        {% endfor %}

    </ul>

</body>
</html>

'month-challenge' 로 등록해둔 url 을 가져오고 pathVarible 엔 month 를 삽입하여 href 를 동적으로 생성하고있다.

 

 

if 태그 사용하기

challenge.html 다음과 같이 수정

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{ month_name }} Challenge</title>
</head>
<body>
    <h1>{{ month_name }} Challenge</h1>
    {% if text is not None %}
        <h2>{{text}}</h2>
    {% else  %}
        <p>There is no challenge for this month yet</p>
    {% endif %}

</body>
</html>

넘겨받은 text 를 if 문 분기처리.

 

 

 

base 템플릿을 이용하기 

1. settings.py 에 다음을 수정

.
.
.
.
.
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            BASE_DIR / "templates"
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

'DIRS' 속성 BASE_DIR / "templates" 추가  

 

base.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{% block page_title%}My Challenges{% endblock %}</title>
</head>
<body>
    <h1>All Challenges</h1>
    {% block content %}{% endblock %}


</body>
</html>

block 태그를이용해서 삽입받을 블럭과 이름을 정의 

path_title 블락의 경우 들어오지 않으면 My Challenges 가 디폴드 값으로 설정 

 

 

challenges/templates/challenges/index.html

{% extends "base.html"  %}

{% block page_title %}
All challenges
{% endblock %}

{% block content%}
<ul>
    {% for month in months %}
        <li><a href="{%  url 'month-challenge' month %}">{{ month|title}}</a></li>
    {% endfor %}

</ul>
{% endblock %}

 

1. settings.py 에서 DIRS 속성을 추가했기 때문에 base.html 을 BASE_DIR/templates 에서 찾음

2. 정의한 block 을 base.html 에 삽입렌더링 .

 

 

 

include 태그 사용법

challenges/templates/challenges/challenge.html

{%  extends "base.html" %}
{% block page_title %}
{{ month_name }} Challenge
{% endblock %}


{% block content %}
    {% include "challenges/include/header.html" with active_page="challenge"%}
    <h1>{{ month_name }} Challenge</h1>
    {% if text is not None %}
        <h2>{{text}}</h2>
    {% else  %}
        <p>There is no challenge for this month yet</p>
    {% endif %}
{% endblock %}

 

include 뒤에 나오는 header.html 은 절대 주소를 써주었다 .

 setting.py  의 INSTALLED_APPS 에 "challenges" 를 추가해주었기 때문에 가능한 일이다!

with 뒤엔 header.html 에만 적용되는 변수를 사용하고 싶을 때 적용한다.

 

challenges/templates/challenges/includes/header.html

<header>
    <nav>
        <a href="{% url 'index' %}">All challenges</a>
    </nav>
    {{ month_name }}
</header>

<p>
    Active_page : {{ active_page }}
</p>

month_name 변수는 밑에 views.py 에서 넘겨준 변수이다 ! 

즉 include 는 상위 템플릿에서 넘어온 변수도 인식이 가능하다 ! 

 

views.py

def monthly_challenge(request, month):

  try:
    challenge_text = monthly_challenges[month]
    return render(request, "challenges/challenge.html",{
      "text": challenge_text,
      "month_name": month.capitalize(),

    })
  except:
    return HttpResponseNotFound("<h1>This month is not supported</h1>")

 

 

'Django' 카테고리의 다른 글

커스텀 404 페이지  (0) 2024.05.06
파이참 장고 HTML 자동 완성 설정하기  (0) 2024.05.05
reverse  (0) 2024.05.02
router 생성  (0) 2024.04.30
파이썬 가상환경 만들기  (0) 2024.04.30