템플릿 파일 모듈화 하기

210731

Extends - 화면 메인 영역 모듈화 하기

잠깐 이야기 할것이 있다. 많은 사람들이 오류가 나는 부분, AssertionError: 301 != 200 오류가 나는 사람들이 있을텐데. 강의에서 함수를 잘못 알려준 것 같다.

models.py

def get_absolute_url(self):
    return f'/blog/{self.pk}'
    
def get_absolute_url(self):
    return f'/blog/{self.pk}/'
  • 전자로 되어있으면 오류가 난다. 후자로 바꿔줄 것

post_detail.html과 post_list.html은 둘 다 동일한 navigation bar를 사용한다. 문제는, 이를 수정하려면 두번 수정해야 한다는 것. 만약 동일한 bar를 사용하는 html이 10개라면 10번 수정할 것인가?

아니다. 이럴 때는 따로 navigation bar를 관리하는 html을 만들 수 있다. 이를 base.html 이라고 하자

base.html

{% block main_area %}
    (id가 main_area인 태그 코드가 있던 곳)
{% endblock %}

기존에 코드를 모두 여기로 붙여넣고 id가 main_area인 태그의 코드만 잘라낸 뒤 위와 같이 추가한다. 그리고 각각의 템플릿에 다음 코드를 추가하면 된다.

post_detail.html post_list.html

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

{% block main_area %}
    (id가 main_area인 태그 코드를 잘라내고 여기에 붙여넣는다)
{% endblock %}

두 템플릿의 네비게이션 바가 동일해진 모습

이렇게되면, 네비게이션 바를 수정할 때 base.html만 수정하면 된다. 이것이 바로 모듈화 하는 이유.

또, 타이틀을 다음과 같이 작성해 줄 수 있다.

base.html

<head>
    <title>{% block head_title %}Blog | 상만두의 웹사이트{% endblock %}</title>
    <link href="{%  static 'blog/bootstrap/bootstrap.min.css' %}" rel="stylesheet" type="text/css">
    <script src="https://kit.fontawesome.com/726bbd6862.js" crossorigin="anonymous"></script>
</head>

이 코드 뜻은 Blog | 상만두의 웹사이트 라고 타이틀을 지정하되, head.title이 있다면 이 것으로 지정하라는 뜻이라고 한다. (나는 직관적으로 이해가 되지 않는 문법이다...)

그래서, post_detail도 수정해주면 된다.

post_detail.html

{% block head_title %}
    {{ post.title }} | Blog
{% endblock %}

Include - 네비게이션바, 푸터 모듈화 하기

일단 예전에 프론트단계에서 사용하던 html 코드를 그대로 가져왔기 때문에, 네비게이션바의 링크들이 제대로 연동이 되어있지 않다. 이를 연동시켜주기 위해 다음을 추가해준다

tests.py

def navbar_Test(self, soup):
    navbar = soup.nav
    self.assertIn('Blog', navbar.text)
    self.assertIn('About me', navbar.text)

    logo_btn = navbar.find('a', text='Do It Django')
    self.assertEqual(logo_btn.attrs['href'], '/')

    home_btn = navbar.find('a', text='Home')
    self.assertEqual(home_btn.attrs['href'], '/')

    blog_btn = navbar.find('a', text='Blog')
    self.assertEqual(blog_btn.attrs['href'], '/blog/')

    about_me_btn = navbar.find('a', text='About me')
    self.assertEqual(about_me_btn.attrs['href'], '/about_me/')
  • post_detail 이나 post_list나 둘다 nav가 공통이므로 nav를 함수로 처리할 수 있도록 했다.

    • 따라서 soup를 인자로 받음

  • 또, 링크를 연결해 주기 위해 navbar.find를 사용해서 실제 텍스트를 찾고 이 텍스트의 href 속성을 링크로 연결해준다.

또, footer나 navbar같은 것을 모듈화 할 필요가 있다. 이 때 footer.html과 navbar.html을 만든 뒤 해당 태그에 해당하는 코드를 각 파일에 잘라내어 붙여넣는다. 그 뒤, base.html 에는 다음과 같이 입력해주면 된다.

  • 물론, 잘라낸 코드 위치에 해야 한다.

base.html

{% include 'blog/navbar.html' %}

{% include 'blog/footer.html' %}

정리하자면, extends과 include 둘 다 템플릿을 불러온다는 점에서 동일하지만 기본이 되는base.html 파일을 기준으로 extends는 자신을 여러 템플릿에서 쓸 수 있도록 바깥으로 보내는 방향이라면, include는 다른 템플릿을 자신의 코드에 붙여넣을 수 있또록 안으로 가져오는 방향이다.

  • 그래서 extends의 경우에는 post_detail.htmlpost_list.htmlbase.html 을 불러와서 쓸 수 있었으며, include의 경우에는 footer.htmlnavbar.html 를 불러와서 base.html 에 쓸 수 있었다.

Last updated

Was this helpful?