[django] 메인 영역 모듈화

haremeat·2021년 11월 30일
1

Django

목록 보기
2/15
post-thumbnail

이번엔 상세 페이지 테스트 코드를 작성해보자

TDD

def test_post_detail(self):
    # 1.1 post가 하나 있다.
    post_001 = Post.objects.create(
        title='첫 번째 포스트입니다.',
        content='Hello Hi'
    )
    # 1.2 그 post의 url은 'blog/1/'이다.
    self.assertEqual(post_001.get_absolute_url(), '/blog/1/')
    # 2.1 첫 번째 post url로 접근하면 정상적으로 작동한다.
    response = self.client.get(post_001.get_absolute_url())
    self.assertEqual(response.status_code, 200)
    soup = BeautifulSoup(response.content, 'html.parser')

    # 2.2 포스트 목록 페이지와 똑같은 내비게이션 바가 있다.
    navbar = soup.nav
    self.assertIn('Blog', navbar.text)
    self.assertIn('About Me', navbar.text)
    # 2.3 첫 번째 포스트의 제목이 웹 브라우저 탭 타이틀에 들어있다.
    self.assertIn(post_001.title, soup.title.text)
    # 2.4 첫 번째 포스트의 제목이 포스트 영역(post_area)에 있다.
    main_area = soup.find('div', id='main-area')
    post_area = soup.find('div', id='post-area')
    self.assertIn(post_001.title, post_area.text)
    # 2.5 첫 번째 포스트의 내용이 포스트 영역에 있다.
    self.assertIn(post_001.content, post_area.text)

test를 돌려보면

Traceback (most recent call last):
File "D:\python_django\DjangoExample\blog\tests.py", line 61, in test_post_detail
self.assertEqual(post_001.get_absolute_url(), '/blog/1/')
AssertionError: '/blog/1' != '/blog/1/'

url이 같지가 안댄다.
고쳐주고 status_code도 301로 고쳐주었다.

Traceback (most recent call last):
File "D:\python_django\DjangoExample\blog\tests.py", line 70, in test_post_detail
self.assertIn('Blog', navbar.text)
AttributeError: 'NoneType' object has no attribute 'text'

네비게이션 바를 못 받아온다.
음...
아직 post_detail 부분에는 네비게이션 바를 제대로 넣지 않아서 뜨는 것.
header를 모듈화해서 post_detail.html 안에 넣어주자

모듈화

base.html파일을 템플릿 폴더 안에 만들고
header와 footer에 해당하는 부분을 넣는다.

<!DOCTYPE html>
{% load static %}
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Blog</title>
    <link rel="stylesheet" href="{% static 'blog/css/blog-post.css' %}" media="screen">
    <link rel="stylesheet" href="{% static 'blog/bootstrap/bootstrap.min.css' %}" media="screen">
    <script src="https://kit.fontawesome.com/437de83aea.js" crossorigin="anonymous"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container">
        <div class="container-fluid">
            <a class="navbar-brand" href="./index.html">Django</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 mr-auto">
                    <li class="nav-item">
                        <a class="nav-link active" aria-current="page" href="./index.html">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="./blog_list.html">Blog</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="./about_me.html">About Me</a>
                    </li>
                </ul>

                <ul class="navbar-nav">
                    <li class="navbar-item">
                        <a href="" class="nav-link">Log In</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</nav>

<div class="container my-3">
    <div class="row">
        <div class="col-md-8 col-lg-9" id="main-area">
            {% block main_area %}
            {% endblock %}
        </div>
        <div class="col-md-4 col-lg-3">
            <div class="card mb-4">
                <div class="card-header">Search</div>
                <div class="card-body">
                    <div class="input-group">
                        <input class="form-control" type="text" placeholder="Enter search term..."
                               aria-label="Enter search term..." aria-describedby="button-search"/>
                        <button class="btn btn-primary" id="button-search" type="button">Go!</button>
                    </div>
                </div>
            </div>

            <!-- Categories widget-->
            <div class="card mb-4">
                <div class="card-header">Categories</div>
                <div class="card-body">
                    <div class="row">
                        <div class="col-sm-6">
                            <ul class="list-unstyled mb-0">
                                <li><a href="#!">Web Design</a></li>
                                <li><a href="#!">HTML</a></li>
                                <li><a href="#!">Freebies</a></li>
                            </ul>
                        </div>
                        <div class="col-sm-6">
                            <ul class="list-unstyled mb-0">
                                <li><a href="#!">JavaScript</a></li>
                                <li><a href="#!">CSS</a></li>
                                <li><a href="#!">Tutorials</a></li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>

        </div>
    </div>
</div>
</body>
</html>

핵심은

{% block main_area %}
{% endblock %}

앞으로 내용이 들어갈 부분에 위 코드를 넣어주면 된다.

{% extends 'blog/base.html' %}

block 안에 들어갈 파일에는 base.html을 extends해주고

{% block main_area %}
{% endblock %}

block 안에 들어갈 내용은 위 코드를 감싸서 넣어주면 모듈화 완성

Ref

장고 + 부트스트랩 파이썬 웹 개발의 정석

profile
버그와 함께하는 삶

1개의 댓글

comment-user-thumbnail
2022년 6월 18일

안녕하세요 혹시 TDD부분에서 URL은 어떻게 코드 수정하셔서 해결하셨나요?

답글 달기