39 HTML 레이아웃 나누기-템플릿상속

39.1 기본 레이아웃 템플릿 만들기 - base.html

HTML에서 공통으로 사용될 부분을 나누는 작업을 하겠습니다.
헤드, 바디, 네비, 푸터로 나누고
css, content, js block 을 만들고 다른페이지에서 상속받아 사용할 것입니다.

38 부트스트랩 적용하기에서
필요해보이는 css와 script만 가져왔습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!-- templates/base/base.html -->
{% load static %}
<!DOCTYPE html>
<html lang="ko">    
    <head><!-- 헤더 영역 -->    
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
    <meta name="description" content="{{descript}}" />
    <meta name="author" content="pythonblog" />
    <title>{{title_nm}}</title>
    {% block css %}
     <link href="{% static 'css/styles.css' %}" rel="stylesheet" />
    {% endblock css %}
    </head> 
    <body class="sb-nav-fixed"><!-- 바디 영역 -->       
        <nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark"></nav><!-- 상단네비 -->
        <div id="layoutSidenav">        
            <div id="layoutSidenav_nav"></div><!-- 좌측네비 -->
            <div id="layoutSidenav_content"><!--  컨텐츠 -->
                <main>
                {% block content %}                 
                {% endblock content %}
                </main> 
                <footer class="py-4 bg-light mt-auto"></footer><!-- 하단 푸터 -->
            </div>
        </nav>
        {% block js %}
        <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/js/all.min.js" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
        <script src="js/scripts.js"></script>       
        {% endblock js %}
    </body>
</html>

39.2 탑바 만들기 - 상단 영역 topbar.html

topbar를 만들겠습니다.

1) 신규파일 topbar.html 생성
2) 템플릿 index.html에서 상단 네비 부분을 topbar.html에 복사합니다.
3) base.html 에 topbar.html을 include 합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- templates/base/base.html -->
{% include 'base/topbar.html' %}


<!-- templates/base/topbar.html -->
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
    <a class="navbar-brand" href="index.html">Start Bootstrap</a>
    <button class="btn btn-link btn-sm order-1 order-lg-0" id="sidebarToggle" href="#"><i class="fas fa-bars"></i></button>
    <!-- Navbar Search-->
    <form class="d-none d-md-inline-block form-inline ml-auto mr-0 mr-md-3 my-2 my-md-0">
        <div class="input-group">
            <input class="form-control" type="text" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2" />
            <div class="input-group-append">
                <button class="btn btn-primary" type="button"><i class="fas fa-search"></i></button>
            </div>
        </div>
    </form>
    <!-- Navbar-->
    <ul class="navbar-nav ml-auto ml-md-0">
        <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" id="userDropdown" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fas fa-user fa-fw"></i></a>
            <div class="dropdown-menu dropdown-menu-right" aria-labelledby="userDropdown">
                <a class="dropdown-item" href="#">Settings</a>
                <a class="dropdown-item" href="#">Activity Log</a>
                <div class="dropdown-divider"></div>
                <a class="dropdown-item" href="login.html">Logout</a>
            </div>
        </li>
    </ul>
</nav>

39.3 사이드바 만들기 - 좌측 영역 sidebar.html

39.2 작업과 동일합니다.

1) 신규파일 sidebar.html 생성
2) 템플릿 index.html에서 좌측네비 부분을 sidebar.html에 복사합니다.
3) base.html 에 sidebar.html을 include 합니다.

39.4 푸터 만들기 - 하단 영역 footer.html

39.2 작업과 동일합니다.

1) 신규파일 footer.html 생성
2) 템플릿 index.html에서 하단푸터 부분을 footer.html에 복사합니다.
3) base.html 에 footer.html을 include 합니다

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<footer class="py-4 bg-light mt-auto">
    <div class="container-fluid">
        <div class="d-flex align-items-center justify-content-between small">
            <div class="text-muted">Copyright &copy; Your Website 2020</div>
            <div>
                <a href="#">Privacy Policy</a>
                &middot;
                <a href="#">Terms &amp; Conditions</a>
            </div>
        </div>
    </div>
</footer>

39.5 index.html 변경하기 및 block 상속받기

extends 는 base.html을 상속 받는다는 뜻 입니다.

index.html의 실제 내용은 block content 영역이며,
base.html의 block content에 해당합니다.

block css, js 는 생략이 가능하며,
block js을 기술하는 이유는 해당 페이지서만 필요로 하는 스크립트가 있을때 사용합니다.
block.super() 은 base.html에 정의된 block js 같이 사용하겠다는 뜻입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{% extends "base/base.html" %}
{% block content %}
<div class="container-fluid">
    <h1 class="mt-4">Dashboard</h1>
    <ol class="breadcrumb mb-4">
        <li class="breadcrumb-item active">Dashboard</li>
    </ol>
    <div class="row">
        <div class="col-xl-3 col-md-6">
            <div class="card bg-primary text-white mb-4">
                <div class="card-body">Primary Card</div>
                <div class="card-footer d-flex align-items-center justify-content-between">
                    <a class="small text-white stretched-link" href="#">View Details</a>
                    <div class="small text-white"><i class="fas fa-angle-right"></i></div>
                </div>
            </div>
        </div>       
    </div> <!-- row -->
</div>
{% endblock %}
{% block js %}
    {{block.super}}      
{% endblock js %}

39.6 브라우져에서 확인하기 - 에러

브라우져로 적용여부를 확인합니다.

scripts.js 과 jquery.js 에러가 발생하여
아래 코드와 같이 수정하였습니다.

1
2
3
4
5
6
7
html
{% block js %}
        <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" crossorigin="anonymous"></script>
        <script src="{% static 'js/scripts.js' %}"></script>        
        <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/js/all.min.js" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
        {% endblock js %}