[Django] Template & View

6 minute read


DJANGO WEB DEVELOPMENT

3. TEMPLATE & VIEW


정적 파일

  • 목표: (foods 앱의) 정적 파일

# 'foods/static/foods' directory 안에 css & fonts & images directory를 각각 만들고 이에 맞는 각 파일 넣기
# 'foods/templates/foods' directory의 index.html 파일 맨 위에 '{% load static %}' 템플릿 테그 넣기
{% load static %}
<!DOCTYPE html>
<html>
<head>
  <title>코스토랑</title>
  <meta charset="utf-8">
...

# '{% static 'foods/[directory_name]'%}' 넣어서 css 경로 수정
  <link rel="stylesheet" href={% static "foods/css/styles.css"%}>
...

# {%static 'foods/[directory_name]'%}
<div class="food">
    <img src={% static "foods/images/chicken.jpg"%} width="300px" height="200px"/>

...

템플릿 & 정적 파일 directroy 구조

<앱_이름>/templates/<앱_이름>/template_files
<앱_이름>/static/<앱_이름>/static_files

Template Language

  • 1) Template Variable(템플릿 변수)
    • 템플릿이 렌더될 때 해당 변수가 의미하는 값으로 변환됨
    • 뷰(View)에서 가공한 데이터를 템플릿으로 넘겨주면 템플릿에서는 템플릿 변수를 사용해 넘겨받은 데이터에 접근할 수 있음
    • 템플릿 변수는 점(.)을 사용해서 변수 안쪽 속성에 접근할 수 있으며(ex. user.name), 다음의 순서로 조회
      • 변수를 사전형(dict)으로 생각하고 점(.) 연산자로 Key값 조회
      • 변수를 객체로 생각하고 내부 속성값 조회 또는 함수 호출
      • 변수를 리스트(list)로 생각하고 점(.) 연산자로 Index 조회
  • 2) Template Filter(템플릿 필터)
    • 일부 필터는 필터 뒤에 인자를 필요로 함
    • Django는 약 60개의 내장 템플릿 필터를 제공하며 개발자가 직접 필터를 정의해서 사용하는 것도 가능, 아래는 일부 내장 템플릿 필터
      • default/ capfirst/ random/ upper & lower/ ljust & rjust
  • 3) Template Tag(템플릿 태그)
    • 템플릿 태그는 템플릿을 작성할 때 반복문, 조건문 등의 로직을 사용해서 마치 프로그래밍을 하듯 템플릿을 작성할 수 있게 해줌
    • Django가 기본적으로 제공하는 태그가 있지만, 개발자가 직접 태그를 정의해서 사용할 수도 있음, 애래는 일부 기본 템플릿
      • for/ if/ with

Template 상속

  • foods/templates/foods/index.html의 ‘index.html’에 대한 부모 템플릿 만들기

# 'foods/templates/foods/' directory의 base.html 생성
# 자식 파일(index.html)의 내용을 cp한 후, 자식 파일에서 작업할 부분은 '{% block [block-name] %} {% endblock [block-name] %}' 입력
<body>
  <div> 
    {% block date-block%}
    {% endblock date-block%} 
  </div>
...

# 자식 파일(index.html) 첫 번째 줄에 {% extends './base.html'%} 입력
# 자식 파일 안에 block 부분 구현
{% extends './base.html'%}
{% load static %}

{% block date-block %}
  <div>12 Aug, 2020</div>
{% endblock date-block %}
...


동적 웹페이지 만들기

  • 템플리 변수 사용하여, 자동으로 Date 변하게끔 하기

# 'foods/' directory의 views.py 파일
# 날짜 가져올 함수를 위해 datetime import 후, index 함수에 date를 today 변수에 저장, 이를 dictionary형에 담아서 template에 넘기기
from django.shortcuts import render
from django.http import HttpResponse
from datetime import datetime

def index(request):
    today = datetime.today().date()
    context = {"date":today}
    return render(request, "foods/index.html", context=context)

# 'foods/templates/foods' directory의 index.html 파일
# today 변수를 '{{key}}'를 통해 가져오기
{% extends './base.html'%}
{% load static %}

{% block date-block%}
  <div>{{date}}</div>
{% endblock date-block%}
...


URL 추가

  • HTML 페이지 내 연결되는 URL 구현

# 'foods/' directory의 urls.py 파일
# 새로 만들 URL인 'foods/chicken' path 추가
urlpatterns = [
    path('index/', views.index),
    path('chicken/', views.chicken)
]

# 'foods/' directory의 views.py 파일
# 새로운 URL을 위한 함수 생성
def chicken(request):
    return render(request, "foods/chicken.html")

# 'foods/templates/foods/' directory에 chicken.html 파일 추가
<h2>코딩에 빠진 </h2>
<div>주머니가 가벼운 당신의 마음까지 생각한 가격!</div>
<div>12000</div>
<a href="/foods/index">돌아가기</a>

# 'foods/templates/foods/' directory의 index.html 파일의 chicken 쪽 경로 변경
...
       <div class="food-container">
        <div class="food">
          <img src={% static "foods/images/chicken.jpg" %} width="300px" height="200px"/>
          <div class="info">
            <h3>코딩에 빠진 </h3>
            <P>주머니가 가벼운 당신의 마음까지 생각한 가격!</p>
            <a href="/foods/chicken">메뉴 보기</a>
         </div>
       </div>
...


우아한 URL

  • DJANGO의 우아한 URL 관리 (DYNMAIC URL)

# 'foods/' directory의 urls.py 파일
# '<str:food>' 부분이 동적으로 만드는 URL을 변수로 처리하게끔 해줌
# 구체적으로 'menu/' 뒤 변수(ex.pizza)가 food_detail 함수의 파라미터가 됨
urlpatterns = [
    path('index/', views.index),
    path('menu/<str:food>', views.food_detail)
]

# 'foods/' directory의 views.py 파일
def food_detail(request,food):
    context = {"name":food}
    return render(request, "foods/detail.html", context=context)

# 'foods/templates/foods/' directory에 detail.html 파일 생성
<h2>{{ name }}</h2>

# localhost:8000/foods/menu/pasta ➡️ 'pasta'가 화면에 나옴
# localhost:8000/foods/menu/pizza ➡️ 'pizza'가 화면에 나옴

DJANGO의 URL 처리

  • URL 처리 순서
    • 1) 처음 요청이 들어오면 Django는 맨 처음 사용할 URLConf 모듈을 찾음, 따로 변경하지 않았다면 프로젝트 앱 내 settings.py의 ROOT_URLCONF 설정을 사용
    • 2) ROOT_URLconf로 정의된 URLConf 모듈을 보고 urlpatterns 리스트 안쪽의 django.urls.path() 함수를 순서대로 실행
    • 3) 요청과 일치하는 URL 패턴이 있다면 django.urls.path() 함수에 따라 view를 호출하거나, 일치하는 URL 패턴 다음의 URL을 하위 URLconf 모듈로 넘김

  • Path 함수 path(route, view, kwargs=None, name=None)
    • route - URL 문자열, 경로 변수(Path Converter)를 사용하여 URL의 일부를 view의 인수로 보낼 수 있음
      • Path Converter
        • str : 경로 구분 기호(/)를 제외한 모든 문자열과 매칭
        • int : 0 또는 양의 정수와 매칭
        • slug : 문자, 숫자, 하이픈(-), 밑줄(_)로 구성된 문자열과 매칭
        • uuid : 범용 고유 식별자(UUID)와 매칭
        • path : 경로 구분 기호(/)를 포함한 모든 문자열과 매칭
    • view - 함수형 view 또는 클래스 기반 view가 들어갈 수 있으며, include를 사용해서 다른 URFconf 모듈로 연결
    • kwargs - view에 추가 인자를 전달 할 때 사용
    • name - path 함수가 가지는 URL 패턴에 이름을 붙여 주기 위해 사용, URL을 직접 템플릿에 적지 않게 하며 URL을 직관적으로 참조할 수 있게 해줌

get_static_prefix


# 'foods/' directory의 views.py 파일
def food_detail(request, food):
    context = {}
    if food == "chicken":
        context["name"] = "코딩에 빠진 닭"
        context["description"] = "주머니가 가벼운 당신의 마음까지 생각한 가격!"
        context["price"] = "10000"
        context["img_path"] = "foods/images/chicken.jpg"
    return render(request, "foods/detail.html", context=context)

# 'foods/templates/foods/' directory에 detail.html 파일
# 
{% load static %}
<h2>{{ name }}</h2>
<div>{{ description }}</div>
<div>{{ price }}</div>
# 템플릿 태크 안에 템플릿 변수 중첩해서 사용할 수 없음, 즉 <img src={% static {{img_path}}%} 하면 에러 남!
<img src={% get_static_prefix%}{{img_path}}/>


에러 코드와 처리

  • 1XX : 정보전달
    • 100 (진행, Continue) : 요청의 첫 부분을 받아서 다음 요청을 기다리고 있다는 것을 알려줌, 이미 요청을 완료했다면 해당 응답을 무시할 수 있음
    • 101 (프로토콜 전환, Switching Protocol) : 클라이언트가 서버에게 프로토콜 전환을 요청했고 서버에서 프로토콜을 변경한다는 것을 나타냄

  • 2XX : 성공
    • 200 (성공, OK) : 클라이언트의 요청이 성공적으로 처리되었다는 것을 의미하며 주로 요청한 페이지를 서버가 제공했다는 것을 알려줌
    • 201 (작성됨, Created) : 요청이 성공적으로 처리되어 새로운 리소스를 생성했다는 것을 의미
    • 202 (허용됨, Accepted) : 서버가 성공적으로 요청을 받았지만 아직 처리 전인 상태를 나타냄
    • 203 (신뢰할 수 없는 정보, Non-Authoritative Information) : 서버가 성공적으로 요청을 처리했지만 요청에 포함된 정보가 다른 곳에서 수정된 정보라는 것을 나타냄
    • 204 (콘텐츠 없음, No Content) : 요청을 성공적으로 처리했지만 콘텐츠를 제공하지 않는다는 것을 의미함
    • 205 (콘텐츠 재설정, Reset Content) : 요청을 성공적으로 처리했고 콘텐츠를 제공하지 않으며 클라이언트가 문서 보기를 재설정할 것을 요구함

  • 3XX : 리다이렉션
    • 300 (여러 개의 선택 항목, Multiple Choice) : 요청에 대해 서버가 여러 응답이 가능하며 하나를 선택해야 함을 나타냄
    • 301 (영구 이동, Moved Permanently : 요청한 리소스가 새로운 위치로 영구 이동했음을 나타냄, 클라이언트는 자동적으로 새로운 위치로 전달됨
    • 302 (임시 이동, Found) : 요청한 리소스가 일시적으로 이동했음을 나타내며 향후 다시 해당 리소스를 요청할 때도 동일한 주소로 해야 한다는 것을 알려줌
    • 304 (수정되지 않음, Not Modified) : 지막 요청 이후 요청한 리소스는 수정되지 않았다는 것을 알려주며 서버가 콘텐츠를 전달하지 않음, 클라이언트는 이전에 전달받은 결과를 계속해서 사용할 수 있습

  • 4XX : 실패
    • 400 (잘못된 요청, Bad Request) : 라이언트의 요청을 서버가 이해할 수 없다는 것을 의미함
    • 401 (권한 없음, Unauthorized) : 클라이언트가 해당 요청에 대한 응답을 받기 위해서는 추가적인 인증이 필요하다는 것을 나타냄
    • 402 (결제 필요, Payment Required) : 이 요청을 결제가 필요하다는 것을 의미하며 처음 이 응답 코드가 만들어질 당시에는 결제 시스템에 사용할 목적이었으나 현재는 사용되고 있지 않음
    • 403 (금지됨, Forbidden) : 클라이언트가 요청한 리소스에 접근할 권한이 없음을 의미함, 401과 다른 점은 서버는 해당 클라이언트에 대한 정보를 가지고 있다는 점임
    • 404 (찾을 수 없음, Not Found) : 클라이언트가 요청한 리소스를 서버가 찾을 수 없다는 것을 의미함

  • 5XX : 서버 오류
    • 500 (내부 서버 오류, Internal Server Error) : 버에서 오류가 발생하여 요청한 작업을 수행할 수 없다는 것을 의미함
    • 501 (구현되지 않음, Not Implemented) : 클라이언트가 요청한 방법을 서버에서 수행할 수 있는 기능이 없다는 것을 의미함
    • 502 (잘못된 게이트웨이, Bad Gateway) : 버가 요청을 처리하는데 필요한 작업 중 게이트웨이로부터 잘못된 응답을 받았다는 것을 의미함
    • 503 (서비스를 사용할 수 없음, Service Unavailable) : 서버가 해당 요청을 처리할 준비가 되지 않았으며 일반적으로는 유지관리를 위해 작동이 중단되거나 과부하가 걸렸을 때를 나타내며 대개 일시적임
# 'foods/' directory의 views.py 파일
# django의 Http404 import
...
from django.http import Http404

# chicken 이외의 요소가 입력될 경우 raise Http404, message도 입력 가능
def food_detail(request, food):
    context = {}
    if food == "chicken":
       ...
    else:
        raise Http404('이런 음식은 없다구요 !')
    return render(request, "foods/detail.html", context=context)