221003_Django Template Language

Csw·2022년 10월 2일
0

Django

목록 보기
6/14

Django Template Language

🛴 템플릿(template) 언어

  • Django의 템플릿 언어(template language)는 강력함과 편리함 사이의 균형을 잡고자 설계됨.
  • 템플릿 언어를 사용하면 HTML 작업을 훨씬 수월하게 할 수 있음.
  • python 변수 및 문법을 html 안에서 쓸 수 있도록 Django에서 제공해주는 언어이기 때문에 html과도 python과도 조금 다름.
  • 하지만 직관적이고 사용하는데 있어서 고도의 학습량을 요구하지 않음.

🛴 템플릿 변수

  • 템플릿 변수를 사용하면 뷰에서 템플릿으로 객체를 전달 가능.
  • 사용 방법 : {{ 변수 }}
  • 점(.)변수의 속성에 접근할 때 사용.

  • Djangoview에서 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번은 여러 줄을 코멘트할 때 코멘트 태그 사이에 코멘트를 작성.
      1. {# #}
      2. {% comment %}
        {% endcomment %}

🛴 템플릿 상속

  • 말 그대로 html 문서 중 기본 뼈대가 되는 문서기본 템플릿으로 정하고, 이는 공통의 코드이므로 다른 문서에서 기본 템플릿의 코드가 필요하면 상속하여 가져다 쓰는 것
  • 기본이 되는 템플릿base.html로 지정.
  • extends를 통해서 어떤 html을 상속받을지를 결정해줌.
  • 다음으로 부모 html에 있는 block``들과 대응시켜 그 안에 내용을 써주면 작성한 내용이 부모 htmlblock` 안으로 들어가서 화면에 출력됨.

    base.html

    list.html

    • base.html 의 내용을 상속받아 가져다 씀.
    • block contentendblock content 사이의 내용을 base.html에 지정한 해당 영역에 넣어서 화면에 출력됨.



🏁 ref

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 사용

📄 list.html

{% 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.namename을 의미.
  • 그리고 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 값으로 해당 변수의 데이터가 동일하게 기재가 되어 있어야함.

📄 enrolled.html

{% 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 nameattendance_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에 연결해준다는 것을 알 수 있음.

0개의 댓글