템플릿(template) 언어Django의 템플릿 언어(template language)는 강력함과 편리함 사이의 균형을 잡고자 설계됨.HTML 작업을 훨씬 수월하게 할 수 있음.python 변수 및 문법을 html 안에서 쓸 수 있도록 Django에서 제공해주는 언어이기 때문에 html과도 python과도 조금 다름.템플릿 변수템플릿 변수를 사용하면 뷰에서 템플릿으로 객체를 전달 가능.{{ 변수 }}점(.) 은 변수의 속성에 접근할 때 사용.Django의 view에서 template으로 context를 전달할 수 있음.CBV 혹은 FBV)에서 html 문서로 어떠한 객체를 보낼 수 있다는 것.
{{ section.title}}
view에서section이라는 객체를html문서로 보냈을 것이고,- 그
section이라는 객체 안에는title이라는 속성을 가지고 있을 것임.
🔥 Django에서는 장고 템플릿 변수를 사용하여 html 문서 상에서도 어떠한 객체의 속성들에 접근할 수 있고, 이를 출력할 수 있도록 지원.
{{ 변수.속성 | 필터 }}|)를 그은 다음 적용하고자 하는 필터를 명시.
{{ story.headline | upper }}
- 여기서,
upper와 같은 것들이 바로템플릿 필터upper라고 명시하였으므로,story.headline의 값을 대문자 형식으로 변환
🔥 위의 링크에서 30개 정도의 필터 내용 확인 가능.
{% %}{% load static %}와 같이 사용할 수도 있고, 위의 예제에서 볼 수 있듯이 if문 또는 for문과 같이 흐름을 제어할 수 있도록 작성도 가능.HTML 문서는 프로그래밍 언어가 아니고 마크업 언어이기 때문에 단지 문서를 웹에서 띄워주는 역할을 하게 됨.HTML 자체는 프로그래밍적 로직을 구현 불가if문, for문와 같은 템플릿 태그를 사용한다면 프로그래밍적 로직을 구현 가능.{% extends %}와 같이 단독으로 사용할 수 있는 템플릿 태그들도 있지만, {% if %} 처럼 뒤에 {% endif %} 템플릿 태그를 반드시 닫아주어야 하는 것들도 있음.🔥 위의 링크에서 상세 내용 확인 가능.
템플릿 코멘트HTML 문서 상에서 코멘트가 필요할 때 사용주석과 비슷한 역할을 하고, 이는 Django로 개발할 시 웹 브라우저에 의해 해석되어 출력되지 않음.Django에서는 두 가지의 코멘트 형식을 제공.1번 형식은 한 줄을 코멘트할 때 사용2번은 여러 줄을 코멘트할 때 코멘트 태그 사이에 코멘트를 작성.
- {# #}
- {% comment %}
{% endcomment %}
템플릿 상속html 문서 중 기본 뼈대가 되는 문서를 기본 템플릿으로 정하고, 이는 공통의 코드이므로 다른 문서에서 기본 템플릿의 코드가 필요하면 상속하여 가져다 쓰는 것base.html로 지정.extends를 통해서 어떤 html을 상속받을지를 결정해줌.html에 있는 block``들과 대응시켜 그 안에 내용을 써주면 작성한 내용이 부모 html의 block` 안으로 들어가서 화면에 출력됨.
base.html
list.html
base.html의 내용을 상속받아 가져다 씀.block content과endblock content사이의 내용을base.html에 지정한 해당 영역에 넣어서 화면에 출력됨.
Django 공식 문서
Opentutorials.org
lks의 코딩일기
Django Template Language 실습Model 설정app/models.py
from django.db import models
class Attendance(models.Model):
# ChoiceField 사용법 알아두기
NONE = "NO"
ATTENDANCE = "AT"
ABSENT = "AB"
PART = "PT"
STATUS_CHOICES = [
(NONE, "미지정"),
(ATTENDANCE, "출석"),
(ABSENT, "결석"),
(PART, "일부참여"),
]
name = models.CharField(verbose_name="이름", max_length=10)
date = models.DateField(verbose_name="날짜")
status = models.CharField(
verbose_name="출석 여부", max_length=2, choices=STATUS_CHOICES, default=NONE
)
description = models.TextField(verbose_name="비고")
def __str__(self):
return f"출석부 : {self.name} ({self.date})"
class Meta:
verbose_name = "출석부"
verbose_name_plural = "출석부 목록"
View 설정app/views.py
from django.shortcuts import redirect
from django.views.generic import TemplateView
from .models import Attendance, Question
# 전체 조회
class AttendanceView(TemplateView):
template_name = "attendance/list.html"
def get_context_data(self, *args, **kwargs):
attendance_qs = Attendance.objects.all().order_by("-date")
context = {}
context["attendance_qs"] = attendance_qs
return context
# 특정 페이지 조회
class AttendanceCreateView(TemplateView):
template_name = "attendance/enrolled.html"
def get(self, request, **kwargs):
response = super(AttendanceCreateView, self).get(self, request)
return response
def post(self, request):
name = request.POST.get("name", None)
date = request.POST.get("date", None)
status = request.POST.get("status", None)
description = request.POST.get("description", None)
Attendance.objects.create(name=name, date=date, status=status, description=description)
return redirect("attendance_list")
URL 설정config/urls.py
이번 실습에서는
app 폴더내에urls.py파일을 생성해서 분리하지 않았음.
from django.contrib import admin
from django.urls import path
from app.views import index, AttendanceView, AttendanceCreateView
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path("admin/", admin.site.urls),
path("attendance/", AttendanceView.as_view(), name="attendance_list"),
path("attendance/create/", AttendanceCreateView.as_view(), name="attendance_create"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
HTML 설정
Django Template Language사용
{% extends "base.html" %}
{% block content %}
<div class="warning hidden">
<h3>** 지난 일정은 출석 여부를 변경할 수 없습니다.</h3>
</div>
<div>
<table class="attendance-table">
<thead>
<tr>
<td>이름</td>
<td>날짜</td>
<td>출석여부</td>
<td>비고</td>
</tr>
</thead>
<tbody>
{% for attendance in attendance_qs%}
<tr>
<td class="name">{{attendance.name}}</td>
<td class="date">{{attendance.date|date:"Y.m.d"}}</td>
<td class="status">{{attendance.get_status_display}}</td>
<td class="description">{{attendance.description}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div>
<button type="button" class="button-bg-full" onclick="location.href='{% url 'attendance_create' %}'">출석체크하기</button>
</div>
{% endblock content %}
{% for attendance in attendance_qs%}관련
attendance-qs
app/views.py파일 내의AttendanceView함수에서
get_context_data함수를 통해Attendance모델 규격에 맞춰db에 저장된 데이터들로 만든QuerySet
-QuerySet:Database에서 전달받은 객체들의 모음(list)attendance
attendance-qs이라고 하는QuerySet내에 있는 요소 객체
Attendance모델에서 정의한field를 본인 객체의 속성 데이터으로 가지고 있음.
{{attendance.name}}관련# list.html <td class="name">{{attendance.name}}</td> <td class="date">{{attendance.date|date:"Y.m.d"}}</td> <td class="status">{{attendance.get_status_display}}</td> <td class="description">{{attendance.description}}</td>
attendance는 위에서 설명한QuerySet내의 요소 객체 각각을 의미.attendance.name은 그 객체 내의 속성을 의미하며, 이는views.py에서 생성한 각각의 변수를 뜻함.# views.py def post(self, request): name = request.POST.get("name", None) date = request.POST.get("date", None) status = request.POST.get("status", None) description = request.POST.get("description", None) Attendance.objects.create(name=name, date=date, status=status, description=description) return redirect("attendance_list")
post함수 내에서name으로 선언한 변수가 바로 위의html파일 내에서 사용한 템플릿 변수attendance.name의name을 의미.- 그리고
post함수 내에서name변수에게request함수를 통해 생성한 값을 할당해주었는데, 이 함수 내의 변수"name"은models.py에서 정의한Attendance모델의field이름을 뜻함.# models.py class Attendance(models.Model): NONE = "NO" ATTENDANCE = "AT" ABSENT = "AB" PART = "PT" STATUS_CHOICES = [ (NONE, "미지정"), (ATTENDANCE, "출석"), (ABSENT, "결석"), (PART, "일부참여"), ] name = models.CharField(verbose_name="이름", max_length=10) date = models.DateField(verbose_name="날짜") status = models.CharField( verbose_name="출석 여부", max_length=2, choices=STATUS_CHOICES, default=NONE ) description = models.TextField(verbose_name="비고", blank=True) def __str__(self): return f"출석부 : {self.name} ({self.date})" class Meta: verbose_name = "출석부" verbose_name_plural = "출석부 목록"
- 현재
Attendance모델은ChoiceField를 사용하였는데, 이는enrolled.html에서form을 이용하여 자료를 입력받을 때 사용.- 예를 들어,
ATTENDANCE = "AT"라는 부분을 보게 되면,ATTENDANCE라는 변수에"AT"라는 값을 할당해주게 되는 것이고,STATUS_CHOICE리스트에서 그"AT"라는 값과"출석"이라는 값을tuple형태로 매칭.- 또한 사용자가 화면을 통해
form을 작성하여 선택하여 POST 요청을 할 경우,"AT"라는 값이 서버로 넘어오게 됨.# enrolled.html <div class="form-item"> <div class="title">출석여부</div> <div class="radio-wrap"> <input type="radio" name="status" value="AT"> <label for="attendance">출석</label> </div> <div class="radio-wrap"> <input type="radio" name="status" value="AB"> <label for="absent">결석 (사유 필히 작성)</label> </div> <div class="radio-wrap"> <input type="radio" name="status" value="part"> <label for="complete">일부 일정 불참 (사유 필히 작성)</label> </div> </div>
- 위에서 보시다 시피,
input태그 내의value값으로 해당 변수의 데이터가 동일하게 기재가 되어 있어야함.
{% extends 'base.html' %}
{% block content %}
<div>
<form method="post" action="">
{% csrf_token %}
<div class="form-item">
<div class="title">이름</div>
<input class="input-box" type="text" name="name" value="">
</div>
<div class="form-item">
<div class="title">날짜</div>
<input class=""input-box" type="date" name="date" value="">
</div>
<div class="form-item">
<div class="title">출석여부</div>
<div class="radio-wrap">
<input type="radio" name="status" value="AT">
<label for="attendance">출석</label>
</div>
<div class="radio-wrap">
<input type="radio" name="status" value="AB">
<label for="absent">결석 (사유 필히 작성)</label>
</div>
<div class="radio-wrap">
<input type="radio" name="status" value="PT">
<label for="part">일부 일정 불참 (사유 필히 작성)</label>
</div>
</div>
<div class="form-item">
<div class="title">사유</div>
<div class="textarea-wrap">
<textarea name="description" form-items="8" cols="50"></textarea>
</div>
</div>
<div class="form-item">
<button class="button-bg-full" type="submit">제출하기</button>
<button class="button-bg-empty" type="button" onclick="location.href='{% url 'attendance_list' %}'">목록보기</button>
</div>
</form>
</div>
{% endblock content %}
URL Template Tag 작성 관련
{% url 'attendance_list' %}
urls.py파일에서url name이attendance_list로 되어 있는url로 연결해주는 경로임을 의미.# urls.py urlpatterns = [ path("admin/", admin.site.urls), path("attendance/", AttendanceView.as_view(), name="attendance_list"), path("attendance/create/", AttendanceCreateView.as_view(), name="attendance_create"), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
- 현재 이 경우에는 웹브라우저를 통해
기본 주소/attendance/로 접속 시, 우리가 미리 지정한html화면을 보여주겠다는 것을 의미.- 지정한
html파일이 무엇인지 확인하기 위해서는 위의 경로에서 사용한View함수로 가서 확인해보면 됨.# views.py class AttendanceView(TemplateView): template_name = "attendance/list.html" def get_context_data(self, *args, **kwargs): attendance_qs = Attendance.objects.all().order_by("-date") context = {} context["attendance_qs"] = attendance_qs return context
- 위의 함수 내에서
template_name = "attendance/list.html부분을 통해, 이 함수가template/attencance/list.html의 위치에 해당하는html파일을 url에 연결해준다는 것을 알 수 있음.