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 %}

[!] /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')

여기서 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 %}" 설정해주면 된다.
'Web > Django' 카테고리의 다른 글
Django / 복습 (0) | 2019.07.01 |
---|---|
Django / form (0) | 2019.07.01 |
Django / 템플릿 동적 데이터와 쿼리셋 (0) | 2019.06.30 |
Django / 데이터 추가/수정/삭제 / HTML / ORM(정규표현식) / 쿼리셋 (0) | 2019.06.29 |
Django / 설정,실행하기,모델(데이터베이스 테이블) 생성 (0) | 2019.06.28 |
댓글