티스토리 뷰

반응형

템플릿은 뷰함수에서 응답하는 html 파일이다.

템플릿이 저장되는 위치는 이미 정해져 있다.

mysite/setting.py

 

에서, 템플릿 환경 설정을 쓴다.

 

TEMPLATES =  [

dirs에다 경로 지정을 한다.

 

]

 

Installed_APPS 에 존재하는 app들의 하위에도 위치할 수 있다.

예를 들어 앱 이름이 blog면, blog/temlplates과 같은 의미이다.

 

첫번째로 dirs에서 찾고, 그 다음에 순서대로 install app에 등록된 순서대로 템플릿을 검색하게 된다.

 

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

 

templates 폴더를 추가해서, html을 넣는다.

이러면 공통으로 사용하는 템플릿을 mysite에 추가해서 넣어주면 된다.

 

만약 각각 쓰려면 blog/templates 처럼 주면 된다.

 

list.html이라고 만들어서, 대충 http를 만든다.

<h1> Post 목록 보기 </h1>

 

render

 

명령문

blog/views.py

from django.shortcuts import render
render(HttpRequest, Template, [context])

 

blog/views.py

def list(request):
	return render(request,'list.html')

http를 응답하게 만들어주는 게 render 함수이다.

인자값을 3개를 줘야 한다. http request와 temlplate, 그리고 context는 선택이다.

 

템플릿 응답

context는 뷰에서 템플릿으로 전달하는 데이터를 말합니다.

context는 key:value 형식의 딕셔너리 타입으로 지정합니다.

 

뷰에서 썼던 데이터를 전달하고 싶다고 하면 딕셔너리 형태로 전달하면 된다.

def list(request):
    post_list = Post.objects.all()
    return render(request,'list.html',{'post_all':post_list})

 

그러면 해당 템플릿에 해당 post_list가 전달된다.

그리고 html에 이렇게 추가하면 된다.

{{post_all}}

 

이렇게 하면 해당 변수를 받는다는 의미이다.

 

그런데 templte의 이름은 중복이 일반적으로 일어난다.

그렇기에 blog/templates/blog/list.html과 같은 경로로 만든다.

shop/templates/shop/list.html

 

이런 상대로 하고, blog/list.html

shop/list.html로 넣는다.

 

템플릿에 온 변수들을 활용하기

post_all을 for문을 돌려볼 수 있다.

{% for 변수 in iterable 객체 %}
	반복실행문
{% endfor %}

여기서는

{%for post in post_all %}
	{{post.id}} 
    {{post.title}}
    {{post.body}}<br>
    
{% endfor %}

 

마찬가지로 detail도 고쳐본다.

views.py

def detail(request, id):
    post = get_object_or_404(Post,id=id)
    return render(request, 'blog/detail.html', {'post': post})

 

blog/detail.html

<h1> {{post.title}} </h1>

제목 : {{post.title}} <br>
내용 : {{post.body}} <br>

 

다음과 같이 만든다.

 

그리고 이제 두 페이지가 연결될 수 있도록 한다.

<h1> Post 목록 보기 </h1>
{%for post in post_all %}
<a href="{{post.id}}"> {{post.title}}</a><br>
{% endfor %}
{% comment %} 출력이라는 의미 {% endcomment %}

 

if 태그 써보기

veiw.py에서 테스트를 넣는다.

def test4(request):
    return render(request, 'bloh/test4.html',{'score':95})

그리고 test4.html을 만들어서 if else문을 넣는다.

새로운 클래스가 만들어졌으므로, path에 추가하는 것도 잊지 말자.

 

path('test4/', views.test4),

 

{% if score >= 60 %}
합격!
{% else %}
불합격!
{% endif %}<br>

<hr>
{{var | linebreaks}}
{% comment %} 필터를 적용한다. linebraks는 줄바꿈을 적용한다. {% endcomment %}
<hr>
{{var | truncatechars:100}}
{% comment %} 100개의 글자만 보여지게 할 수 있다. {% endcomment %}

 

필터

아래에 있는 건 필터이다.

{{값 | 필터}}
{{ 값 1 | 필터 : 값2}}
{{값1 | 필터 1: 값2 } 필터 2}}

 

시간 설정

setting.py

Lanugae_code ="ko-kr"

time_znoe = "Aisa/Seoul"

USE_I18N = True

USE_TZ = True

 

혹은

blog/views.py에서 설정할 수 있다.

from django.utils import timezone

def test6(request):
    d1 = timezone.now()
    d2 = timezone.datetime(2001,3,19)
    d3 = timezone.datetime(2030,3,19)
    
    return render(request, 'blog/test4.html', {'date1':d1, 'date2':d2, 'date3':d3})

 

문법으로는 {{미래날짜 | timeuntil}}

 

{{d1}} <br>
{{d1|date: "Y-m-d"}} <br>
{{d1|time: "P" }} <br>
{{d2|timesince}}<br>
{{d3|timeuntil}}<br>

 

https://docs.djangoproject.com/en/4.2/ref/templates/builtins/#date

 

해당하는 시간에 대한 포맷팅을 넣어줘야 한다.

 

timesince는 {{ 과거날짜 | timesince : 미래날짜}}로 쓴다. 과거부터 미래날짜까지 시간을 알려준다.

timeuntil은 {{미래날짜 | timeuntil: 미래날짜2}}로 쓴다. 미래날짜부터 미래날짜2까지 시간을 알려준다.

 

템플릿 상속

원래 있던 템플릿을 상속받아서 사용할 수 있다.

 

부모 템플릿은 공통 코드를 구현한다.

자식이 채워넣어야 하는 부분을 영역 설정해준다.

{% block 이름 %}

{% endblock %}

 

자식 템플릿은 부모 템플릿 경로를 써넣어준다.

여기서는 layout.html을 사용한다.

mysite/아래 templates에 가져다 놓는다. mysite/mysite 아니다. 거기에 넣으면 인식 못한다.

{% extends "부모템플릿 경로" %}
{% extends "layout.html" % }

 

 

blog/templates/blog/list.html

 

이 경로에 있는 것 상속받아본다. mysited에 있으므로, 위 코드와 같이 넣어도 된다.

 

여기서는 2개를 채워넣을 수 있다.

<html>
<head>
    <meta charset="utf-8" />
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
    <style>
        html {position: relative; min-height: 100%}
        body{margin-bottom: 60px}
        #page-footer{
            position: absolute;
            bottom: 0;
            width:100%;
            height: 60;
            line-height: 60px;
            background-color: #f5f5f5;
        }
    </style>
</head>
<body>
    <nav class="navbar navbar-default">
        <div class="container">
            <div id="navbar" class="collapse navbar-collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="/blog/">Home</a></li>
                    <li><a href="#">About</a></li>
                    <li><a href="#">Contact</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">회원 가입 </a> </li>
                    <li><a href="#">로그인</a></li>
                    <li><a href="#">프로필</a> </li> 
                    <li><a href="#">로그 아웃</a></li>
                 </ul>
                </div>
        </div>
    </nav>
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                {% block content %}
                {% endblock %}
            </div>            
        </div>
    </div>

    <div id="page-footer">
        <div class="container">
            <p class="text-muted">
                Copyright © 2020 KINO Data Systems All Right Reserved
            </p>
        </div>
    </div>
</body>
</html>

 

title과 content를 채워넣는다.

{% extends "layout.html" %}

{% block title %}  
    Post 목록
{% endblock %}

{% block content %}

    <h1> Post 목록 보기 </h1>
    {%for post in post_all %}
    <a href="{{post.id}}"> {{post.title}}</a><br>
    {% endfor %}
    {% comment %} 출력이라는 의미 {% endcomment %}

{% endblock %}

 

detail에도 같은 방식으로 채워준다.

{% extends "layout.html" %}

{% block title %}  
    
{% endblock title %}

{% block content %}
    <h1> {{post.title}} </h1>
    제목 : {{post.title}} <br>
    내용 : {{post.body}} <br>

{% endblock content %}

 

실습

1:N 관계를 수정해준다.

detail에서 comment_list를 추가

def detail(request, id):
    post = get_object_or_404(Post,id=id)
    
    comment_list =post.comments.all()
    return render(request, 'blog/detail.html', {'post': post, 'comment_all':comment_list})

 

detail.html에서도 수정해준다.

 

{% block content %}
    <h1> {{post.title}} </h1>
    제목 : {{post.title}} <br>
    내용 : {{post.body}} <br>

    <hr>
    <p>댓글</p>
    {% for comment in comment_all %}
        <p> {{comment.message}}/{{comment.author}}/{{comment.updated}}</p>
    {% empty%}
        댓글이 존재하지 않습니다.
    {% endfor %}
{% endblock content %}

 

만약에 버그가 있다면, models의 comments에서, 사용자 정의가 되어 있는지 봐보자.

post= models.ForeignKey(Post, on_delete=models.CASCADE,related_name='comments')

 

1:1 관계

veiws.py

from .models import User

def profile(request):
    user = User.objects.get(id=1)
    return render(request, 'blog/profile.html', {'user': user})

사용자 이름을 불러온다.

 

그리고 profile.html에서 새로운 html을 만들어준다.

{% extends "layout.html" %}

{% block title %} Profile {% endblock title %}

{% block content %}
<h1>{{ user.name }}'s Profile</h1>
<ul>
    <li>이름 : {{ user.name }}</li>
    <li>전화번호 : {{ user.profile.phone_number }}</li>
    <li>주소 : {{ user.profile.address }}</li>
</ul>
{% endblock content %}

당연히 새 페이지가 추가되었으니, urls.py에도 추가해준다.

 

path(('profile/', views profile)

 

그리고, templates/layout.html을 수정해준다.

<ul class="nav navbar-nav navbar-right">
    <li><a href="#">회원 가입 </a> </li>
    <li><a href="#">로그인</a></li>
    <li><a href="/blog/profile/">프로필</a> </li> 
    <li><a href="#">로그 아웃</a></li>
 </ul>
</div>

프로필을 누르면 해당 페이지로 갈 수 있게 해준다.

 

N:M 관계

디테일에서 tag_list도 추가해준다.

views.py이다.

def detail(request, id):
    post = get_object_or_404(Post,id=id)    
    comment_list =post.comments.all()
    tag_list = post.tag.all()
    return render(request, 'blog/detail.html', {'post': post, 'comment_all':comment_list,
                                                'tag_list':tag_list})

 

detail.html에서 태그를 추가해준다.

당연히 content란 안이다.

<hr>
<p>태그</p>
    {% for tag in tag_list %}
        #{{tag.name}}
    {% endfor %}

 

모델에 있는 태그를 누르면, 해당 태그와 연관된 포스트를 보려면

 

blog/views.py

from .models import Tag

def tag_list(request, id):
    tag = Tag.objects.get(id=id)
    post_list = tag.post_set.all()
    return render(request, 'blog/list.html', {'post_all': post_list})

urls.py

path('tag/<id>/', views.tag_list),

 

detail.html

<p>태그</p>
{% for tag in tag_list %}
    <a href="/blog/tag/{{tag.id}}">{{tag.name}}</a>
{% endfor %}

 

다음과 같이 하면 된다.

반응형