프로그램 애플리케이션 확장하기

지금까지 웹 사이트 제작 단계를 모두 마쳤어요. 모델, url, 뷰와 템플릿을 만드는 방법을 알게 되었고요. 웹 사이트를 예쁘게 꾸미는 방법도 알게 되었어요.

이제 또 실습해봅시다!

블로그 게시글이 각 페이지마다 보이게 만들어 봅시다.

이미 앞에서 Post모델을 만들었으니 models.py에 새로 추가할 내용은 없어요.

Post에 템플릿 링크 만들기

blog/templates/blog/post_list.html파일에 링크를 추가하는 것부터 시작합시다. 아래와 같이 보일 거에요. :

blog/templates/blog/post_list.html

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

{% block content %}
    {% for post in posts %}
        <div class="post">
            <div class="date">
                {{ post.published_date }}
            </div>
            <h1><a href="">{{ post.title }}</a></h1>
            <p>{{ post.text|linebreaksbr }}</p>
        </div>
    {% endfor %}
{% endblock content %}

post제목 목록이 보이고 해당 링크를 클릭하면, post상세 페이지로 이동하게 만들어 볼 거에요. <h1><a href="">{{ post.title }}</a></h1>부분을 수정해 봅시다.

blog/templates/blog/post_list.html

<h1><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h1>

{% url 'post_detail' pk=post.pk %}을 설명할 때가 왔군요! {% %}는 장고 템플릿 태그을 말합니다. URL를 생성해 사용해봅시다.

blog.views.post_detailpost_detail 경로입니다. blog는 응용프로그램(디렉터리 blog)의 이름인 것을 꼭 기억하세요. viewsviews.py파일명이에요. 마지막 부분 post_detailview 이름입니다.

pk = post.pk이란 무엇일까요? pk는 데이터베이스의 각 레코드를 식별하는 기본키(Prmiary Key)의 줄임말 입니다. Post 모델에서 기본키를 지정하지 않았기 때문에 장고는 pk라는 필드를 추가해 새로운 블로그 게시물이 추가될 때마다 그 값이 1,2,3 등으로 증가하게 됩니다. Post 객체의 다른 필드 (제목, 작성자 등)에 액세스하는 것과 같은 방식으로 post.pk를 작성하여 기본 키에 액세스합니다 post.pk를 써서 기본키에 접근할 수 있고 같은 방법으로 Post객체내 다른 필드(title, author)에도 접근할 수 있습니다!

이제 http://127.0.0.1:8000/ 를 열어보세요. 아마 오류 메세지가 나올 거에요. (아직 post_detail 를 만들지 않아 오류가 나는 거에요) 이런 화면이 보일 거에요. :

NoReverseMatch error

Post 상세 페이지 URL 만들기

post_detail가 보이게 urls.py에 URL를 만들어 봅시다!

첫 게시물의 상세 페이지 URLhttp://127.0.0.1:8000/post/1/가 되게 만들 거에요.

blog/urls.py파일에 URL을 만들어, 장고가 post_detail 로 보내, 게시글이 보일 수 있게 해봅시다. url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail')코드를 blog/urls.py파일에 추가하면 아래와 같을 보일 거에요.

blog/urls.py

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.post_list, name='post_list'),
    url(r'^post/(?P<pk>\d+)/$', views.post_detail, name='post_detail'),
]

^post/(?P<pk>[0-9]+)/$부분이 복잡하게 보이지만, 걱정하지 마세요. 하나씩 차근차근 알아봅시다.

  • ^은 "시작"을 뜻합니다.
  • post/란 URL이 post 문자를 포함해야 한다는 것을 말합니다. 아직 할 만하죠?
  • (?P<pk>[0-9]+)는 조금 까다롭습니다. 이 정규표현식은 장고가 pk변수에 모든 값을 넣어 뷰로 전송하겠다는 뜻입니다. [0-9]은 문자를 제외한 숫자 0부터 9 중, 한 가지 숫자만 올 수 있다는 것을 말합니다. +는 하나 또는 그 이상의 숫자가 올 수 있습니다.. 따라서 http://127.0.0.1:8000/post/라고 하면 post/ 다음에 숫자가 없으므로 해당 사항이 아니지만, http://127.0.0.1:8000/post/1234567890/는 완벽하게 매칭됩니다.
  • /은 다음에 / 가 한 번 더 와야 한다는 의미입니다.
  • $는 "마지막"을 말합니다. 그 뒤로 더는 문자가 오면 안 됩니다.

브라우저에 http://127.0.0.1:8000/post/5/라고 입력하면, 장고는 post_detail 를 찾아 매개변수 pk5인 값을 찾아 로 전달합니다.

pkprimary key의 약자로, 장고에서 많이 사용되는 변수명입니다. 변수명은 내가 원하는 것으로 변경할 수 있어요. (변수명에 공백문자는 사용할 수 없으며 소문자와 _를 사용할 수 있음을 주의하세요) 예를 들어, (?P<pk>[0-9]+)변수를 post_id으로 바꾸면, 정규표현식도 (?P<post_id>[0-9]+)으로 바뀌게 됩니다.

좋아요, 새로운 URL 패턴을 blog/urls.py에 추가했어요! 페이지를 새로고침 하세요. http://127.0.0.1:8000/ 쾅! 또 에러가 났어요! 예상했던 대로에요!

AttributeError

다음 단계는 무엇일까요? 그렇죠. 뷰를 추가해야죠!

Post 상세 페이지 내 뷰 추가하기

에 매개변수 pk를 추가해봅시다. pk를 식별해야겠죠? 그래서 함수를 def post_detail(request, pk):라고 정의합니다. urls(pk)과 동일하게 이름을 사용해야 합니다. 변수가 생략되면 오류가 날 거예요!

블로그 게시글 한 개만 보려면, 아래와 같이 쿼리셋(queryset)을 작성해야해요.

blog/views.py

Post.objects.get(pk=pk)

하지만 이 코드에는 문제가 있어요. 만약 해당 primary key(pk)Post를 찾지 못하면 오류가 나올 거에요!

DoesNotExist error

우리가 원하는게 아니죠! 장고에는 이를 해결하기 위해 get_object_or_404라는 특별한 기능을 제공해요. pk에 해당하는 Post가 없을 경우, 멋진 페이지(페이지 찾을 수 없음 404 : Page Not Found 404)를 보여줄 거에요.

Page not found

나중에 페이지 찾을 수 없음(Page not found)페이지를 예쁘게 만들 수 있어요. 지금 당장 중요한 것이 아니니 이 부분은 생략할게요.

좋아요. 이제 views.py파일에 새로운 를 추가합시다!

blog/views.py파일을 열고 아래 코드를 추가하세요.

blog/views.py

from django.shortcuts import render, get_object_or_404

from행 가서, 파일 마지막 부분에 를 추가하세요.

blog/views.py

def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'blog/post_detail.html', {'post': post})

그리고 브라우저를 새로고침 하세요. http://127.0.0.1:8000/

Post list view

잘 작동하네요! 그런데 블로그 제목 링크를 클릭하면 어떻게 되나요?

TemplateDoesNotExist error

이런! 또 에러가 나왔네요! 하지만 이제 어떻게 해야하는지 알고 있죠? 드디어 템플릿을 추가할 차례에요!

Post 상세 페이지 템플릿 만들기

blog/templates/blog 디렉터리 안에 post_detail.html라는 새 파일을 생성하고 아래와 같이 코드를 작성하세요.

blog/templates/blog/post_detail.html

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

{% block content %}
    <div class="post">
        {% if post.published_date %}
            <div class="date">
                {{ post.published_date }}
            </div>
        {% endif %}
        <h1>{{ post.title }}</h1>
        <p>{{ post.text|linebreaksbr }}</p>
    </div>
{% endblock %}

다시 한 번 base.html을 확장한 거에요. content블록에서 블로그 글의 게시일, 제목과 내용을 보이게 만들었어요.

가장 중요한 부분은 {% if ... %} ... {% endif %}라는 템플릿 태그인데, 내용이 있는지 확인할 때 사용합니다. (if ... else ..구문은 Python 시작하기 장에서 배웠어요) post게시일(published_date)이 있는지, 없는지를 확인하는 거에요.

페이지를 새로고침하면 페이지 찾을 수 없음(Page not found) 페이지가 없어졌어요.

Post detail page

야호! 잘 되네요!

한 가지만 더 합시다. 배포하세요!

PythonAnywhere에도 웹사이트가 잘 작동하는지 봐야겠죠? 다시 한 번 배포합시다.

command-line

$ git status
$ git add --all .
$ git status
$ git commit -m "Added view and template for detailed blog post as well as CSS for the site."
$ git push

command-line

$ cd my-first-blog
$ git pull
[...]
  • 마지막으로 Web tab에서 Reload(다시 불러오기) 를 누르세요.

배포를 마쳤습니다. 잘 작동되는지 확인해 보세요! 축하합니다.

results matching ""

    No results matching ""