Old Branch

장고(Django) 예제 / 북마크 프로젝트 - 4. 템플릿 확장과 꾸미기

woolbro 2019. 7. 25. 11:10
반응형

안녕하세요~! 이전 포스팅까지 장고를 활용해서 기본적인 기능들을 작성 했습니다. 장고 어드민 페이지, 어드민페이지의 커스터마이징을 했었고, 조회 페이지를 비롯해서, CRUD까지 작성을 했습니다. 

 

이번 포스팅은, 만든 페이지 템플릿을 확장하고, 꾸며보려고 합니다. 이전 포스팅은 아래의 접은글에서 확인 하실 수 있습니다.

 

...더보기

 

템플릿 확장하기

웹서비스를 둘러보면, 어느 페이지든 동일하게 보여지는 내용 들이 있습니다. 베뉴 바, 타이틀 같은 부분들이 공통적으로 볼 수 있는 대표적인 예 입니다. GNB(Global Navigation Bar) 라고 부릅니다.

 

장고에서는 '템플릿 확장' 이라는 방법을 사용 해서 레이아웃 템플릿을 따로 만들어 두고, 기존 템플릿에 상속받아 사용하는 방법입니다.

 

프로젝트 루트 폴더의 template에 base.html이라는 파일을 만들어 보도록 하겠습니다.

위처럼 폴더를 만들고 작성 해 주세요.

 

위의 폴더를 생성했다고 해서 바로 사용 할 수 있는 것은 아니구요, settings.py가 (장고가) 이 tempate을 인식 할 수 있어야 합니다.

 

config/settings.py로 들어가서 템플릿 파일을 사용 할 수 있도록 해 보겠습니다.

 

TEMPLATES의 옵션으로 들어가서, 'DIRS' 란에 os.path.join(BASE_DIR,"templates") 를 추가 해 주세요

 

config/settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(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',
            ],
        },
    },
]

 

이제 방금 생성한 루트폴더의 templates/base.html을 수정하도록 하겠습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}</title>
</head>
<body>

    {% block content %}

    {% endblock %}

</body>
</html>

 

위에 보면 특이한 태그가 있습니다. {% bloock %} {% endblock %} 의 태그를 볼 수 있습니다.

 

장고(Django)의 템플릿확장은 block 을 기준으로 동작합니다. 외부에서 작성한 파일이 block 안에 들어가는 형태입니다.

 

이 블록에 맞게 나머지 템플릿을 수정 해 보도록 하겠습니다.

 

bookmark/tmeplates/bookmark/bookmark_confirm_delete.html

{% extends 'base.html' %}

{% block title %}Confirm Delete{% endblock %}

{% block content %}
<form action="" method="post">
    {% csrf_token %}
    <div class="alert alert-danger">Do you want to delete Bookmark "{{object}}"??</div>
    <input type="submit" value="Delete" class="btn btn-danger">
</form>

{% endblock %}

 

위의 코드를 잘 보면, <title></title>에 있던 내용이 {% block title %} {% endblock %} 안으로 들어가고, <body> </body>의 내용이

{% block content %} {% endblock%} 으로 들어 간 것을 볼 수 있습니다.

 

다른 나머지 create, update, detail, list 템플릿도 위와같이 적용 해 줍니다.

 

bookmark/tmeplates/bookmark/bookmark_create.html

{% extends 'base.html' %}

{% block title %}woolbro bookmark{% endblock %}

{% block content %}
    <form action = "" method = "post">
        {% csrf_token %}
        {{form.as_p}}
        <input type = "submit" value="Add" class = "btn btn-info btn-sm">
    </form>
{% endblock %}

 

bookmark/tmeplates/bookmark/bookmark_detail.html

{% extends 'base.html' %}

{% block title %}woolbro bookmark{% endblock %}

{% block content %}
    {{object.site_name}}<br/>
    {{object.url}}
{% endblock %}

 

bookmark/tmeplates/bookmark/bookmark_list.html

{% extends 'base.html' %}

{% block title %}woolbro bookmark{% endblock %}

{% block content %}
    <div class="btn-group">
        <a href ="{% url 'add' %}" class = "btn btn-info">Add Bookmark</a>
    </div>
    <p></p>
    <table class = "table">
        <thead>
            <tr>
                <th scope = "col">#</th>
                <th scope = "col">Site</th>
                <th scope = "col">URL</th>
                <th scope = "col">Modify</th>
                <th scope = "col">Delete</th>
            </tr>
        </thead>
        <tbody>
            {% for bookmark in object_list %}
            <tr>
                <td>{{forloop.counter}}</td>
                <td><a href="{% url 'detail' pk=bookmark.id %}">{{bookmark.site_name}}</a></td>
                <td><a href="{{bookmark.url}}" target="_blank">{{bookmark.url}}</a> </td>
                <td><a href="{% url 'update' pk=bookmark.id %}" class="btn btn-success btn-sm">Modify</a></td>
                <td><a href="{% url 'delete' pk=bookmark.id %}" class="btn btn-danger btn-sm">Delete</a></td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
{% endblock %}

 

bookmark/tmeplates/bookmark/bookmark_update.html

{% extends 'base.html' %}

{% block title %}woolbro bookmark{% endblock %}

{% block content %}
    <form action = "" method = "post">
        {% csrf_token %}
        {{form.as_p}}
        <input type = "submit" value="Update" class = "btn btn-info btn-sm">
    </form>
{% endblock %}

 

서버를 실행시켜서 정상동작을 확인하면 완료입니다!!

 

 

부트스트랩 적용하기

부트스트랩을 우리의 북마크 페이지에 적용 시켜보도록 하겠습니다!! 아래의 링크를 클릭하거나, 부트스트랩을 검색해서 공식 홈페이지로 접속을 해 줍니다!

https://getbootstrap.com/

 

Bootstrap

The most popular HTML, CSS, and JS library in the world.

getbootstrap.com

상단의 Documentation을 눌러, Quick Start를 찾아줍니다!

 

이렇게 나올텐데요, CSS와 JS를 복사 한 후에 base.html에 적용시켜 주도록 하겠습니다.

templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</head>
<body>

    {% block content %}

    {% endblock %}

</body>
</html>

 

적용된 화면을 확인 해 보도록 하겠습니다.

 

전에 비해서, 버튼과 링크, 테이블이 좀더 예쁘게 된 것을 볼 수 있습니다.

 

부트스트랩을 사용해서 디자인을 만들었으니, 조금 더 수정해서 메뉴 바도 만들어보도록 하겠습니다.

 

base.html파일의 내용을 수정 해 주겠습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</head>
<body>
    <div class="container">
        <nav class = "navbar navbar-expand-lg navbar-light bg-light">
            <a class="navbar-brand" href="#"> Django Bookmark</a>
            <button class="navbar-toggler" type="button" data-toogle="collapse" data-target="#navbarSupportedContent" aria-label="Toggle navigation">
                <span class ="navbar-toggler-icon"></span>
            </button>

            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav mr-auto">
                    <li class="nav-item active">
                        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span> </a>
                    </li>
                    <li class="nav-item active">
                        <a class="nav-link" href="https://woolbro.tistory.com">woolbro<span class="sr-only">(current)</span> </a>
                    </li>
                </ul>
            </div>
        </nav>
        <p></p>
        <div class="row">
            <div class="col">
                {% block content %}

                {% endblock %}


                {% block pagination %}
                {% endblock %}
            </div>
        </div>
    </div>
</body>
</html>

 

맨 아래쪽에 {% block pagination %}을 보셨나요??

 

페이징 기능도 추가 해 보도록 하겠습니다!

 

페이징 기능 만들기

페이징 기능은 게시판의 기능 중 필수 기능입니다. 클래스 형 뷰를 만든 우리는, 페이징을 간단하게 작성 할 수 있습니다.

 

bookmark/views.py 의 BookmarkListView 클래스에 코드를 더해 주도록 하겠습니다.

class BookmarkListView(ListView):
    model = Bookmark
    paginate_by = 6

그리고, bookmark_list.html파일의 하단에 페이징 기능을 넣어주겠습니다.

 

bookmark/templates/bookmark/bookmark_list.html

{% block pagination %}
{% if is_paginated %}
<ul class="pagination justify-content-center pagination-sm">
    {% if page_obj.has_previous %}
    <li class="page-item">
        <a class="page-link" href="{% url 'list' %}?page={{ page_obj.previous_page_number }}" tabindex="-1">Previous</a>
    </li>
    {% else %}
    <li class="page-item disabled">
        <a class="page-link" href="#" tabindex="-1">Previous</a>
    </li>
    {% endif %}

    {% for object in page_obj.paginator.page_range %}
    <li class="page-item {% if page_obj.number == forloop.counter %} disabled {% endif %} ">
        <a class="page-link" href="{{ request.path }}?page={{ forloop.counter }}">{{ forloop.counter }}</a>
    </li>
    {% endfor %}

    {% if page_obj.has_next %}
    <li class="page-item">
        <a class="page-link" href="{% url 'list' %}?page={{ page_obj.next_page_number }}">Next</a>
    </li>
    {% else %}
    <li class="page-item disabled">
        <a class="page-link" href="#">Next</a>
    </li>
    {% endif %}
</ul>
{% endif %}
{% endblock %}

 

위의 코드를 페이지 가장 하단에 넣어주면 됩니다.

 

현재는 글이 4개밖에 없기 떄문에 처음에 설정한 paginated_by = 6 의 갯수 까지는 페이징이 나타나지 않습니다!

 

 

정적(Static) 파일 사용하기

정적 파일은, 로컬 서버에 있는 여러가지 파일을 의미합니다. css, js 등이나  이미지 파일을 포함합니다.

이런 파일들을 장고에서 사용하는 방법을 알아 보겠습니다.

 

정적파일도 템플릿(templates) 파일 처럼 정해진 위치가 있습니다. 각 앱 폴더 밑에 static 폴더를 사용합니다.

마찬가지로 사용시에는 settings.py에서 설정을 해 주어야 합니다.

 

config/settings.py의 맨 아랫 부분에 아래와 같은 설정을 추가 해 줍니다.

STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

그리고, 루트폴더에 아래와 같이 static 폴더를 추가 해 줍니다.

 

이곳에 css를 작성 해 보도록 하겠습니다.

body{
    width:100%;
}

그리고, base.html에서 위의 css를 불러서 사용 해 주도록 하겠습니다.

    {% load static %}
    <link rel="stylesheet" href="{% static 'style.css' %}">

base.html의 <head> 부분에 위의 코드를 넣어주고 확인 해 보도록 하겠습니다.

 

확인을 위해 서버를 실행시킨 후에 화면에서는 크게 변화가 없어보입니다.

 

크롬 -> 개발자도구로 들어가서 확인을 해 주도록 하겠습니다!

 

static 폴더 안에, 우리가 작성한 style.css가 있습니다! 

 

지금까지 장고를 활용한 간단한 앱을 만들어 보았습니다!! :)