Django에서 웹페이지의 기본 프레임 구조를 잡는 법을 살펴본다. Django template 기능 중 하나인 block 요소를 사용하여 프레임 구조를 잡고 마지막에 부트스트랩을 사용해서 메뉴바를 조금 더 세련되게 변경해보자.
다음 내용을 알아본다.
- 장고 프로젝트 및 App 생성
- 장고 block을 사용한 메뉴 프레임 구성
- 부트스트랩을 사용하여 네비게이션 바 구성
- 부트스트랩을 사용하기 위한 장고 static 설정
개발환경
- Python 3.9 ( 3.6 이상 요구 됨 )
- Django 3.1.5 ( 3.1 이상 요구 됨 )
- Bootstrap 5.x
프로젝트 및 App 생성
C:\django_exam> django-admin startproject sitemenu
C:\django_exam>cd sitemenu
C:\django_exam\sitemenu> python manage.py startapp demo
settings.py에 App 등록
INSTALLED_APPS = [
'demo.apps.DemoConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
demo/templates/base.html
- base.html는 상단, 사이드 메뉴바가 있고 메인 컨텐츠를 출력하는 block 코드( {% block content %} {% endblock %} )가 있다. Django에서 block은 templates의 주요 기능이다.
- main 컨텐츠에 출력되는 모든 html은 base.html 을 extends하여 static 소스 부터 메인 프레임 위치가 지정된 block content를 얻게 되고 각 화면에서는 block content 안에 내용을 넣는다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Demo{% endblock %}</title>
<style>
.topnav {
top: 0;
height: 60px;
width: 100%;
position: fixed;
z-index:1;
background-color:#02343F;
overflow: hidden;
display: flex;
justify-content: center;
}
.topnav .center {
display:flex;
align-items:center;
}
.topnav a {
text-align: center;
margin: 0px 5px 0px 5px;
}
a {
color: #F0EDCC;
text-decoration: none;
font-size: 25px;
}
a:hover {
color: white;
}
.sidemenu {
height: 100%;
width: 200px;
position: fixed;
z-index:1;
top: 60px;
left: 0;
background-color:#02343F;
overflow-x: hidden;
padding-top: 20px;
}
.sidemenu li {
margin:10px;
}
.wrap_content {
margin-top: 70px;
margin-left: 210px;
margin-right: 10px;
}
ul {
list-style:none;
list-style-position: outside;
}
body {
margin: 0px;
background-color: #F0EDCC;
}
</style>
</head>
<body>
<div class="topnav">
<div class="center">
<div class="menu">
<a href="{% url 'demo:home' %}">Home</a>
<a href="{% url 'demo:board' %}">Board</a>
</div>
</div>
</div>
<div class="sidemenu">
<ul>
<li><a href="{% url 'demo:home' %}">home</a></li>
<li><a href="{% url 'demo:board' %}">board</a></li>
<li><a href="#">menu3</a></li>
<li><a href="#">menu4</a></li>
<ul>
</div>
<div class="wrap_content">
<div id="content" name="content" class="container">
{% block content %}
{% endblock %}
</div>
</div>
</body>
</html>
demo/templates/index.html
- home.html, board.html을 만들고 index.html의 내용을 카피한다. ( 변경 된 페이지를 확인하기 위해 컨텐츠 내용을 변경하자 )
{% extends 'base.html' %}
{% block title %}Index page{% endblock %}
{% block content %}
<style>
.card {
padding: 10px;
}
.card h3 {
font-family: none;
}
</style>
<h2>Index Page</h2>
<div style="display:flex;">
<div class="card" style="width:33%;">
<h3>Django</h3>
Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.
</div>
<div class="card" style="width:33%;">
<h3>Django</h3>
Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.
</div>
<div class="card" style="width:33%;">
<h3>Django</h3>
Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.
</div>
</div>
{% endblock %}
1. {% extends 'base.html' %} 코드로 base.html을 확장한다.
2. {% block content %} ... html ... { % endblock %} 안에 컨텐츠 내용을 넣는다.
sitemenu/urls.py
from django.contrib import admin
from django.urls import path, include
from demo import views
urlpatterns = [
path('', views.index, name='index'),
path('demo/', include('demo.urls'))
]
1. Indes url과 demo App의 urls.py에 정의된 url을 include 한다.
demo/urls.py ( 신규생성 )
from django.urls import path
from . import views
app_name = 'demo'
urlpatterns = [
path('', views.index, name='index'),
path('board/', views.board, name='board'),
path('home/', views.home, name='home'),
]
1. app_name 을 demo로 등록하여 네임스페이스를 지정한다.
2. 메뉴바에서 연결되는 home, board의 url을 등록한다.
demo/views.py
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'index.html', {'title':'data'})
def home(request):
return render(request, 'home.html', {'title':'home'})
def board(request):
return render(request, 'board.html', {'title':'board'})
1. urls.py에 매핑된 view 객체를 생성한다.
결과페이지
Bootstrap 사용하여 메뉴바 변경
아래 부트스트랩 다운로드 페이지에서 소스를 다운받는다.
getbootstrap.com/docs/5.0/getting-started/download/
압축을 풀면 css / js 폴더가 있다. 폴더채로 demo/static/demo 폴더에 넣는다.
demo/templates/base.html
base.html 제일 상단에 {% load static %} 코드를 넣으면 static 요소에 접근 할 수 있다. base.html을 확장하고 있는 html들은 static 자원을 별도로 로드 할 필요 없다.
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Demo{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{% static 'demo/css/bootstrap.css' %}">
<script src="{% static 'demo/js/bootstrap.js' %}"></script>
.. 이하 생략
1. {% static "url" %} 을 사용하여 css, js파일을 로드한다.
부트스트랩 자원을 제대로 로드 하는지 확인한다.
- F12로 개발자도구 창을 열어 Network에서 제대로 로드 되었는지 확인한다.
부트스트랩 css 영향을 받아 일부 div의 모습이 변경되었다.
base.html의 내용을 변경하여 메뉴바를 변경한다. (navbar는 공식레퍼런스사이트에 공개된 내용을 가져왔다.)
demo/templates/base.html 전체 소스
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Demo{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{% static 'demo/css/bootstrap.css' %}">
<script src="{% static 'demo/js/bootstrap.js' %}"></script>
<style>
.wrap_content {
margin-top: 20px;
}
body {
margin: 0px;
background-color: #F0EDCC;
}
</style>
</head>
<body>
<!--
<div class="topnav">
<div class="center">
<div class="menu">
<a href="{% url 'demo:home' %}">Home</a>
<a href="{% url 'demo:board' %}">Board</a>
</div>
</div>
</div>
-->
<!--
<div class="sidemenu">
<ul>
<li><a href="{% url 'demo:home' %}">home</a></li>
<li><a href="{% url 'demo:board' %}">board</a></li>
<li><a href="#">menu3</a></li>
<li><a href="#">menu4</a></li>
<ul>
</div>
-->
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">My demo app</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link {% if title == 'home' %} active aria-current='page' {% endif %}" href="{% url 'demo:home' %}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link {% if title == 'board' %} active aria-current='page' {% endif %}" href="{% url 'demo:board' %}">Board</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</ul>
<form class="form-inline justify-content-center" style="text-align: center;">
<input class="form-control mr-sm-2" type="search" placeholder="Search for" aria-label="Search">
</form>
</div>
</div>
</nav>
<div class="wrap_content">
<div id="content" name="content" class="container">
{% block content %}
{% endblock %}
</div>
</div>
</body>
</html>
style 태그가 대부분 없어지면서 코드가 한결 가벼워졌다. ( 사이드 메뉴를 살리고 싶다면 사이드 메뉴바의 div를 풀면된다. )
결과 페이지
마무리하며..
Django의 메뉴프레임을 셋팅하고 정적 자원(css, js)을 어떻게 관리하는지 알아보았다. block 요소는 Django template 기능 중 핵심기능이다. 이를 사용해서 subcontent 영역이나 footer영역을 나눌 수 있다.
부트스트랩을 잘 사용하면 많은 효과를 볼 수 있다. 잘 꾸며진 다양한 컴포넌트와 이를 화면에 배치하는데 제공되는 여러 class 요소를 제공한다. 웹 페이지 디자인 요소에 약한 개발자에게는 더 좋은 선택지가 될 것이다. ( 나같은 사람에겐 너무 고마운 존재다. ㅠㅠ )
다음에는 부트스트랩 이해 제고를 위해 본 블로그에서 생성한 페이지에 주요 기능들을 구현해 본다.
'python > Django' 카테고리의 다른 글
4. 게시판 만들기 - Django 템플릿 & 페이징(Pagination) 처리( feat. GIF ) (0) | 2021.02.04 |
---|---|
3. 게시판 만들기 - Django 게시판 목록, 읽기, 쓰기 페이지 구성 (0) | 2021.02.04 |
Django templates 날짜(datetime) 포맷 변경 및 UTC 설정 (0) | 2021.02.03 |
2. 게시판 만들기 - Django + mariaDB 연동( 접속부터 모델생성까지 - migration ) (0) | 2021.02.01 |
1. 게시판 만들기 - Django 3.x 설치 및 핵심개념 파악 (0) | 2021.02.01 |