IT/WEB

[Django] 검색 게시판 만들기 ③ : 게시판 목록 페이지 만들기

개발자 두더지 2020. 9. 13. 02:11
728x90

이제 Admin페이지 등록한 게시글 목록을 화인할 수 있는 목록 페이지를 만들어보고자 한다.

 

URL정의


search/ulrs.py를 열어 아래와 같이 url을 등록해준다.

from django.urls import path
from . import views

app_name = 'search'

urlpatterns = [
    path('', views.PublicPostIndexView.as_view(), name='top'),
]

 

뷰의 작성


search/views.py파일을 열어 포스트 목록을 보여주도록 아래와 같이 작성하자.

from django.views import generic
from .models import Post


class PublicPostIndexView(generic.ListView):
    """게시글의 목록을 표시한다."""
    model = Post

우선은 단순한 목록만을 표시할 수 있도록 짧은 코드로 작성하였다. 검색 폼이나 페이징 처리 등에 대해 설명할 때 코드를 수정할 예정이다. 

 

템플릿 파일의 작성


 목록을 표시할 html파일을 작성하자. 우선 search앱 폴더에 templates 폴더을 만들고 다시 search 폴더를 만든 후 거기서 base.html (search/templates/search/base.html) 과 post_list.html (search/templates/search/post_list.html)을 만들자.

 base.html에는 다음과 같이 코드를 작성하자.

{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="keywords" content="{% block meta_keywords %}Python,Django,프로그래밍,게시판{% endblock %}">
    <meta name="description" content="{% block meta_description %}Python/Django를 중심으로 프로그래밍의 메모나 튜토리얼에 대해 작성하고 있습니다.{% endblock %}">
    <title>{% block meta_title %}Mole Blog{% endblock %}</title>
    <link rel="stylesheet" href="{% static 'search/css/style.css' %}">
    <link rel="stylesheet" href="https://use.typekit.net/wfe6byb.css">
    <script>
      (function(d) {
        var config = {
          kitId: 'jjv2htu',
          scriptTimeout: 3000,
          async: true
        },
        h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
      })(document);
    </script>
    {% block extrahead %}{% endblock %}
</head>
<body>

<main>
    <div class="container">
        {% block content %}{% endblock %}
    </div>
</main>

<footer id="site-footer">
    <div class="container" id="footer-container">
        <p id="copyright">© 2020 Engineer Mole.</p>
    </div>
</footer>

</body>
</html>

 자식 템플릿으로의 덮어쓰기용으로 {% block %}태그를 몇 개 사용하고 있다. 그 외에는 간단하다 12행째의 script태그 부분에는 일본어를 웹에서 표시하기 위해 작성할 것이다. Adobe Fonts에는 일본어의 웹 폰트를 읽어들일 때 위와 같이 작성할 것이다. 

 Bootstrap4나 Bluma등과 같은 CSS 프레임워크는 사용하지 않을 것이다. 그러므로 CSS 파일은 내용이 길어질 것으로 별도의 파일로 작성할 것이다. CSS파일이 위치할 곳을 만들기 위해 다시 search 앱 아래에 static폴더를 만들고, 거기서 다시 search폴더를 만든 후 또 다시 css폴더를 작성하여 style.css파일을 만들자 (search/static/search/css/style.css). 물론 파일 경로를 인식시면 될 뿐이라 본인이 원하는 곳에 파일을 만들어도 상관없다. 파일 경로를 인식시키는 곳은 위 코드의 첫 번째 link태그에 href = "{% static 'search/css/style.css'}" 부분이다. 이것은 Djang로 정적 파일을 이용할 때의 방법이다.

 한편 post_list.html로써는 다음과 같은 템플릿 파일을 작성하였다.

{% extends 'search/base.html' %}
{% load humanize %}
{% block meta_title %} 게시글 목록 {{ block.super }}{% endblock %}

{% block content %}
    <section>
        {% for post in post_list %}
            <article class="post">
                <h2 class="post-title"><a href="#">{{ post.title }}</a></h2>
                <p class="description">{{ post.description }}</p>
                <div>
                    <time class="updated_at"
                          datetime="{{ post.updated_at | date:'Y-m-d' }}">{{ post.updated_at | naturaltime }}に更新
                    </time>

                    {% for tag in post.tags.all %}
                        <span class="tag" data-pk="{{ tag.pk }}">{{ tag.name }}</span>
                    {% endfor %}
                </div>
            </article>

        {% empty %}
            <p class="post">まだ記事がありません。</p>
        {% endfor %}
    </section>
{% endblock %}

{% load humanize %}로써 사용하고 있는 naturaltime은 날짜형의 데이터를 넘겨주면 'X시간 전'이라는 친절한 표현으로 리턴해주는 필터이다. Django에 소속되어 있는 어플리케이션으로 이 필터를 사용하기 위해서는 프로젝트의 settings.py의 INSTALLED_APPS에 django.contrib.humanize라고 기재해줘야한다.

 

css 파일 작성


css는 본인이 작성하기 나름이지만, 나는 다음과 같이 작성하였다.

@charset "UTF-8";

/*
공통설정
*/

* {
    margin: 0;
}

body {
    line-height: 1;
    color: #333;
    font-family:  neue-haas-grotesk-text, noto-sans-cjk-jp, sans-serif;
    font-size: 14px;
}


@media (min-width: 768px) {
    body {
        font-size: 16px;
    }
}

a {
    text-decoration: none;
    color: #00809d;
}

a:hover {
    opacity: 0.5;
    text-decoration: underline;
}

p {
    line-height: 1.75;
}


/*
유틸리티
*/
/* 컨테이너 */
.container {
    margin: 0 10px;
}

@media (min-width: 768px) {
    .container {
        margin: 0 40px;
    }
}

@media (min-width: 1024px) {
    .container {
        width: 960px;
        margin: 0 auto;
    }
}


/* 메인 컨텐츠 */
main {
    padding: 48px 0;
    min-height: 40vh;
}


/* 푸터 */
#site-footer {
    background-color: #00809d;
    padding: 48px 0;
    color: #fff;
}

/* 게시글 관련 */
.post {
    margin-bottom: 48px;
    position: relative;
}

h2.post-title, h3.post-title {
    line-height: 1.5;
    font-size: 18px;
    font-weight: bold;
}

.updated_at {
    display: block;
    line-height: 1.5;
    color: #6F959E;
    font-size: 14px;
    margin-top: 5px;
}

.description {
    font-size: 14px;
    margin-top: 5px;
}

.tag {
    margin-right: 5px;
    cursor: pointer;
    color: #00809d;
    font-size: 14px;
}

.tag:hover {
    opacity: 0.5;
    text-decoration: underline;
}

 먼저 모든 요소의 margin을 0으로 해둔다. 브라우저의 표준의 설정을 사용하기 힘들거나, 각 브라우저에서의 설정값이 다른 경우가 있으므로 이와 같이 설정을 리셋, 통일하는 경우가 종종 있다. padding도 0으로 하거나 다양한 방법이 있지만, margin정도는 모두 0으로 해두는 것이 좋다.

 body의 요소에는 폰트의 종류와 시이즈, 색을 지정하고 있다. 로마자 폰트는 Neue Haas Grotesk(Helvetica와 비슷한 것)으로 일본어 폰트는 Noto Sans CJK JP, 폰트 사이즈는 14px가 기본으로 사용될 수 있도록 하였다. 색 #333은 아주 살짝 옅어진 검은색이다. 또한 margin의 계산도 쉽게 하기 위해 line-height는 1로 하였다.

@media (min-width: 768px) 부분은 iPad(세로)등에 적용되는 것으로 이것보다 큰 경우에는 기본 폰트 사이즈를 16px로 하고 있다. 즉, 가로 폭이 큰 화면에서는 문자 사이즈도 크게 하기 위함이다.

 a요소의 설정은 링크의 선 아래에 밑줄을 없애기 위해 #00809d라는 녹색과 비슷한 청색으로 하고 마우스 오버할 때 투명으로 하도록 하는 것이다.

 p요소는 행간의 넓혀 line-height를 1.75로 하였다. 

 contatiner은 콘텐츠 폭의 설정이다. 일기 사이트 제작에서 설정하였지만, 이 설정에 의해 클래스를 사용하기 쉽게 된다.

 메인 콘텐츠 부분이 되는 main요소와 푸터의 footer요소는 위의 48px의 여백을 붙였다. 또한 main요소는 최소 40vh의 높이를 가지도록 하였다. 브라우저나 화면의 높이의 4배이지만 이 정도의 높이를 높이를 가지도록 하지 않으면 표시 데이터 수가 적을 때는 모양이 이상하게 되어버린다.

 푸터에는 링크에도 사용하고 있는 색을 배경색으로 하고 중간의 글자는 하얀색으로 하였다.

 

여기까지 작성하여 완성된 이미지는 아래와 같다.

다음은 검색 기능을 추가해보자!


참고자료

blog.narito.ninja/detail/174/

blog.narito.ninja/detail/175/

728x90