Django 템플릿과 css
기초 화면 구성, css와 Bootstrap을 활용한 스타일 적용
0. 개요¶
바로 로그인/로그아웃, 회원가입 등 주요 기능으로 넘어가고 싶지만, 화면이 없어 만들어도 확인을 할 수가 없으니 일단 화면부터 만들기로 한다.
1. 템플릿 폴더 설정¶
템플릿은 HTML을 동적으로 생성해주는 기능을 해서 Front-end 화면을 쉽게 만들 수 있게 해준다.
Django 프로젝트에서 사용할 템플릿을 생성하기 전에, 우선 config/settings.py
에서 TEMPLATES
항목을 아래와 같이 수정해준다.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], # use common templates folder
'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',
],
},
},
]
위와 같이 설정하면 root 디렉토리의 templates
폴더에서 모든 템플릿을 통합하여 편리하게 관리할 수 있다.
2. 질문 목록/세부 내용 화면¶
2-1. view 생성¶
board_qnd/views.py
파일을 아래와 같이 수정해 질문 목록을 보여주는 index
view와 질문의 세부 내용을 보여주는 detail
view를 만들어 준다.
from django.shortcuts import render, get_object_or_404
from .models import Question
# Create your views here.
def index(request):
"""index view for question_list"""
question_list = Question.objects.order_by('-id') # order by id desc
context = {'question_list': question_list}
return render(request=request, template_name='board_qna/question_list.html', context=context)
def detail(request, question_id):
"""view for details of each question"""
question = get_object_or_404(Question, pk=question_id) # returns 404 instead of 500 when requested not existing question_id
context = {'question': question}
return render(request, 'board_qna/question_detail.html', context)
order_by
는 QuerySet API로, QuerySet은 데이터베이스에서 가져온 객체들의 모음을 말한다. QuerySet API에 대한 자세한 설명은 공식 문서를 참고하자.
render
는 템플릿과 데이터를 조합하여 HttpResponse
객체로 반환하는 함수로, 자세한 설명은 공식 문서를 참고하자.
2-2. URL 매핑¶
위에서 만든 view들의 링크를 매핑해주기 위해 board_qna/urls.py
파일을 아래와 같이 수정해준다.
from django.urls import path
from . import views
app_name = 'board_qna'
urlpatterns = [
path('', views.index, name='index'), # name parameter is to set name of url variable for template
path('<int:question_id>/', views.detail, name='detail'), # url for listing board_qna
]
<int:question_id>
에서 볼 수 있듯이 변수를 활용한 URL을 매핑해주려면 angle brackets으로 감싸주면 되고, 해당 변수를 특정 타입으로 변환하도록 지정할 수 있다. 자세한 내용은 공식 문서를 참고하자.
2-3. 템플릿 생성¶
앞에서 index
view에서 지정한 question_list.html
템플릿을 templates/board_qna
폴더에 아래와 같이 생성해준다.
<h1>Hello World! Welcome to Q&A board.</h1>
{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="{% url 'board_qna:detail' question.id %}">{{ question.id }} {{ question.subject }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>질문이 없습니다.</p>
{% endif %}
{% url [URL_name] %}
태그는 URL 매핑을 사용할 수 있도록 해준다. 자세한 내용은 공식 문서를 참고하자.
templates/board_qna
폴더에 question_detail.html
파일을 아래와 같이 생성해준다.
admin 권한으로 샘플 데이터를 몇 개 생성한 후 확인해보면 결과물을 아래 화면과 같이 확인할 수 있다.
Django에서는 Django 템플릿 언어를 사용해서 템플릿을 작성한다. Jekyll에서 사용하는 liquid와 별 차이는 없는 것 같다.
3. 스타일 적용¶
3-1. static 기초 설정¶
static은 웹 페이지에 정적 디자인을 부여해준다. Django 프로젝트에 사용할 디자인을 통합하여 관리하기 위해 config/settings.py
에서 Static
항목을 아래와 같이 수정해준다.
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
위와 같이 설정하면 root 디렉토리의 static
폴더에서 모든 스타일을 통합하여 편리하게 관리할 수 있다.
3-2. 스타일시트 작성¶
원래라면 static/style.css
파일을 생성해 css로 스타일을 만들어줘야 하나 빠르게 구현해보기 위해 Bootstrap을 사용하기로 한다. 본 프로젝트에서는 v5.2를 사용했다.
Bootstrap 홈페이지에서 Compiled CSS and JS를 다운받아 bootstrap.min.css
파일과 bootstrap.min.js
파일을 static
디렉토리에 저장하자.
3-3. 기본 템플릿 생성 및 포함¶
templates
디렉토리에 <html>
, <head>
, <body>
태그를 포함하여 표준 HTML 문서의 구조를 가지고, 템플릿 상속을 통해 다른 템플릿의 기초가 되는 base.html
을 먼저 생성한다.
{% load static %}
<!doctype html>
<html lang="ko">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" type="text/css" href="{% static 'bootstrap.min.css' %}">
<!-- board_qna CSS -->
<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">
<title>Hello, World!</title>
</head>
<body>
<!-- nav bar -->
{% include "navbar.html" %}
<!-- content start -->
{% block content %}
{% endblock %}
<!-- content end -->
<!-- Bootstrap JS -->
<script src="{% static 'bootstrap.min.js' %}"></script>
</body>
</html>
템플릿 포함¶
{% include [source] %}
태그는 다른 템플릿을 포함시킨다는 뜻으로, 아래 코드는 해당 위치에 navbar.html
을 포함시켜서 같이 렌더링 한다는 뜻이다.
스타일 적용¶
템플릿에 스타일을 적용하려면 아래와 같이 {% load static %}
태그와 <link>
태그를 사용해서 연결해주면 된다.
3-4. 내비게이션 바 추가¶
templates
디렉토리에 아래와 같이 navbar.html
템플릿을 생성해준다.
<nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom">
<div class="container-fluid">
<a class="navbar-brand" href="/">Hello World!</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" href="{% url 'board_qna:index' %}">Q&A</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">로그인</a>
</li>
</ul>
</div>
</div>
</nav>
내비게이션 바는 모든 화면 상단에서 공통적으로 보여줘야 하므로 아래와 같이 base.html
파일에서 <body>
의 가장 위에 {% include [source] %}
태그를 이용하여 공용 템플릿에 포함시켜준다.