Django / 프로그램 애플리케이션 확장
Web/Django

Django / 프로그램 애플리케이션 확장

뉴비뉴 2019. 6. 30.

Post 상세 페이지 URL 만들기

-post_detail 뷰가 보이게 urls.py 에 URL을 만들어 봅시다.

-첫 게시물의 상세 페이지 URL이 http:/127.0.0.1:8000/post/1 가 되게 만들 것이다.

 

1. blog\urls.py

urlpatterns = [

    url(r'^$', views.post_list, name='post_list'), # ^문자열의 시작 $문자열의 끝

    url(r'^post/1$', views.post_detail, name='post_detail'),

] # post.detail function 이 없다고 오류가 발생한다.

 

2. blog\views.py

def post_detail(request):

   return render(request, 'blog/post_detail.html')

 

3. blog\post_detail.html 생성

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

   {% block content %}

      Hello, Post Detail

   {% endblock %}

header 부분은 {% extends "blog/base.html" % 을 상속받아서 자동으로 출력된다.

[!] /post/1 에 대한 url은 생성이 다 되었다, 만약 여기서 /2 /3 /4 를 더 추가하고 싶다면 urls.py에서 추가해주면 된다.

하지만 이렇게 추가하게 되면 아래와 같이 코드가 복잡해지고, 얼마나 많은 페이지가 있을지 모른다.

 

url(r'^post/1$', views.post_detail, name='post_detail'),
url(r'^post/2$', views.post_detail, name='post_detail'),
url(r'^post/3$', views.post_detail, name='post_detail'),
url(r'^post/4$', views.post_detail, name='post_detail'),
url(r'^post/5$', views.post_detail, name='post_detail'),
url(r'^post/6$', views.post_detail, name='post_detail'),

정규표현식으로 줄일 수 있다. 만약 페이지가 300페이지 까지 있다고하면 url(r'^post/(?P\d\d\d')/$' 로 지정할 수 있고

만약 몇개까지 나올지 모르겠다라고 생각이 들면 url(r'^post/(?<pk>P\d+)/$' pk라는 이름으로 post_detail 함수에다가 인자로 넘기겠다는 뜻이다.

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

views.py로 가서 pk를 추가시켜 준다.

def post_detail(request, pk):
    return render(request, 'blog/post_detail.html')

url /100000 을 입력하여도 페이지가 출력되는 걸 확인할 수 있다.

여기서 post/1 이 입력되면 1번 포스팅을 보여주고 싶다.

def post_detail(request, pk): pk에는 1이 입력되면 1이 pk에 들어오고, 100이 입력되면 100이 들어온다.

def post_detail(request, pk):
    # pk = "1"
    post = Post.objects.get(pk=pk) # 앞에 pk는 어떤 필드인지 필드를 뜻하는 것(필드명), 뒤에는 인자로 받은 pk 변수이다.
    return render(request, 'blog/post_detail.html', {
        'post' : post, # 인자로 획득한 pk를 템플릿에다가 post라는 이름으로 넘겨준다.
    })

url 에 대한 설정을 다 끝났다. 이제 post_detail.html 에 입력된 pk에 맞는 게시글(post)을 출력해보자.

#post_detail.html
    {% extends "blog/base.html "%}
        {% block content %}
            <h2> {{ post.title }}</h2>
            {{ post.text }}
        {% endblock %}

하지만 위위 코드에는 문제가 있다. 만약 primary key(pk) 의 Post를 찾지 못하면 오류(Error 500)가 나올 것이다.

ex) 삭제나 비공개로 변경 될 경우

해결방법으로는

try:
        post = Post.objects.get(pk=pk) # 앞에 pk는 어떤 필드인지 필드를 뜻하는 것(필드명), 뒤에는 인자로 받은 pk 변수이다.
    except Post.DoseNotExist:
        raise Http404 # Page Not Found : from django.http import Http 404

하지만 이렇게 사용하면 매번 예외처리를 해줘야되서 번거로우니 Django는 Shortcuts에서 해당 기능을 갖고 있다.

from django.shortcuts import get_object_or_404, render


def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    # try:
    #     post = Post.objects.get(pk=pk) # 앞에 pk는 어떤 필드인지 필드를 뜻하는 것(필드명), 뒤에는 인자로 받은 pk 변수이다.
    # except Post.DoseNotExist:
    #     raise Http404 # Page Not Found : from django.http import Http 404
    return render(request, 'blog/post_detail.html', {
        'post' : post, # 인자로 획득한 pk를 템플릿에다가 post라는 이름으로 넘겨준다.
    })

post = get_object_or_404(Post, pk=pk) 가 아래 주석처리되어있는 것과 똑같은 기능을 하게 된다.

 

URL Reverse

페이지에서 링크를 누르면 해당 링크의 페이지로 이동된다.

#post_list.html

   {% extends "blog/base.html "%}
        {% block content %}
            {% for post in post_list %}
                <div class="post">
                    <div class="date">
                        <p>published: {{ post.published_date }}</p>
                    </div>
                    <h1><a href="/post/{{ post.pk }}">{{ post.title }}</a></h1>
                    <p>{{ post.text|linebreaksbr }}</p>
                </div>
            {% endfor %}
        {% endblock %}

하지만 post_list.html 에는 한개의 a태그가 있고, 거기에 만약 <a href="post/1"> 이라고 지정해주면 어떤 링크를 누르던 간에 전부 다 post/1 로 이동하게 될 것이다. 이 때 "/post/{{ post.pk}}" 이렇게 지정하게 된다면 해당 post 가 갖고 있는 pk 주소로 이동하게 된다. 매우 편리한 기능이다.

하지만 urls.py 에서 urlpatterns가 변경이 되면 방금 코드도 수정이 되어야하는데 바뀔 일이 많은데 바뀔 때 마다 해당 경로를 가지는 주소를 찾아서 변경해주는 건 비효율적이다. 이럴 땐

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

"{% url "post_detail" post.pk %}" 설정해주면 된다.

댓글

💲 추천 글