본문 바로가기
개발/Django_python 웹 프레임워크

Blog project_pk, path converter, get_object_or_404

by 자유로운 코끼리 2020. 7. 9.
728x90

우선 앞부분에서 db연결을 마친 후 글을 써주면 다음과 같은 화면을 볼 수 있습니다.

저는 여기서 첫 페이지에 보이는 body글자 수를 제한한 뒤, '...더보기'를 누르면

상세보기 페이지로 넘어가도록 짜보려고 합니다.

 

1. 글자 수 제한하기

 

글자 수를 제한하기 위해 summary라는 함수를 만들어볼께요.

 

#models.py

    def summary(self):
        return self.body[:100]  

 

2. index.html에서  글자 수를 제한한 뒤 '...더보기' 글자 추가 후 링크달기

 

#index.html

{% for blog in blogs.all %}
    <h1> {{blog.title}} </h1>
    <p> {{blog.pub_date}} </p>
    <p> {{blog.summary}}<a href>...더보기</a></p>
    <br><br>
{% endfor %}

3. 링크 url연결

자, 여기서 생각하셔야 할 부분이있습니다.

더보기를 누르면 detail.html로 넘어가야 하는데, 

그럼 게시물 수 만큼의 detail.html을 만들어줘야 할까요?

출처: 멋쟁이 사자처럼

그렇다면 너무 비효율적이겠죠?

 

그래서 우리는 detail.html 페이지는 하나만 만들고,

선택된 번호의 Blog 객체 내용을 띄우는 코드를 짜볼거에요.

출처: 멋쟁이 사자처럼

그림과 같이 하나의 html에 n번째 객체를 보여주기 위해서는 다음과 같은 과정이 필요합니다.

 1) n번째 블로그 객체를 요청하면 n번 객체의 내용을 띄우기. -> pk(primary key) 

 2) url => 사이트/detail/객체번호(n) -> path Converter

 3) 없는 페이지, 즉 없는 객체를 요청하면 404 에러 띄우기 -> get_object_or_404 함수

 

우선 url부터 어떻게 설정해주어야 하는지 보겠습니다.

path('detail/<int:blog_id>',modelapp.views.detail,name="detail"),

path는 path('url이름', 함수이름, path이름)의 형태를 띄고 있습니다.

이때 <>path converter라고 하는데, <type(int, str 등): 변수이름>의 형태를 띄고 있습니다.

기존의 url 은 숫자를 쓰더라도 str 타입으로 인식을 하는데 <>와 int를 통해 정수형으로 바꿔줍니다.

 

이 <int:blog_id>는 '지정한 converter type(int)으로 변환한 변수(blog_id)를 view 함수로 넘겨라'라는

의미를 가지고 있습니다.

즉, 원래 url은 string type이지만, blog_id를 int형으로 변환하여 함수에게 넘겨준다는 거죠.

예를 들어 detail/1이 url을 부르게 되면 blog_id=1이 되어, blog_id를 view 함수로 넘어가게 됩니다.

 

이는 주로 계층적인 url을 다룰 때 사용합니다.

 

 

이제 views.py에서 함수를 만들 때,

이때까지 우리는 index.html을 달라고 요청이 들어올 때 index를 실행시키면 되었습니다.

def index(request):
    blogs = Blog.objects #모델로부터 객체의 목록을 전달, 쿼리셋
    return render(request,'index.html',{'blogs':blogs})

하지만 이제는 요청도 필요하지만, 몇 번째 블로그 객체에 대한 것인지도 필요합니다.

그래서 인자가 2개가 되는거죠.

(url에서 blog_id라는 변수로 보냈기에 함수에서 받을 때도 blog_id로 받음)

def detail(request, blog_id):

그리고 이제 번호에 해당하는 객체를 보내주어야 하는데,

이때 get_object_or_404함수를 이용합니다.

우선 import를 해주고요.

from django.shortcuts import render, get_object_or_404
def detail(request, blog_id):
    blog_detail = get_object_or_404(Blog, pk=blog_id)
    return render(request, '/detail.html', {'blogdetail': blog_detail})

get_object_or_404함수는 2개의 인자를 받는데,

get_object_or_404(어떤 클래스, 검색조건(pk)) 형태를 띈다.

 

우선 어떤 클래스로부터 정보를 가져올지에 대한 정보를 알려주어야 합니다.

우리는 Blog라는 클래스에서 정보를 가져오니 Blog라고 적어줍니다.

그리고 pkprimary key의 약자로 모델에서 찍어낸 수많은 객체들을 구분할 수 있는 구분자라고 할 수 있습니다.

하나의 클래스에서 여러 게시물들이 찍어내질텐데, 이를 구분해주는 이름표 같은 거죠!

데이터를 구분 지을 수 있는 이름표, 데이터의 대표값으로 볼 수 있겠네요.

그러니 중족될 수 없는 단일 값이어야겠죠?

 

어떤 값을 데이터의 대표값으로 삼을지는 정의하기 나름입니다.

모델에서 따로 pk를  주지 않아도, pk는 꼭 필요한 아이라서

id가 자동으로 pk가 되어 식별자 역할이 됩니다.

 

다만 따로 pk를 주고 싶다면, 모델에서

class Blog(models.Model):
      my_pk = models.IntegerField(primary_key=True)

 

우리는 url에서 blog_id로 받아왔으니, view에서도 blog_id를 pk를 가져와야합니다.

view는 urls.py에 적었던 pk를 식별하기 때문입니다.

 

자, 우리는 이제 blog 객체의 id값으로 데이터를 가져와,

있으면 보여주고 없으면 404 에러를 띄워줍니다.

예를 들어 db에 만든 적 없는 1000번째 url을 불러주면-

404에러가 보이쥬/

 

이때 객체의 id는 쟝고가 자동으로 만들어줍니다.

 

자 이제 url과 view를 만들어주었으니 main.html과 detail.html을 연결시켜줄께요!

 

main.html로 가서 a태그에 다음 url을 넣어줍니다.

{% for blog in blogcontent.all %}
    <h1> {{blog.title}} </h1> 
    <p> {{blog.pub_date}} </p>
    <p> {{blog.sum}}<a href="{% url 'detail' blog.id %}">...더보기</a></p>
    <br><br>
{% endfor %}

더보기 링크에 {% url 'detail' blog.id %}이런 아이가 붙었죠.

이 blog.id가, 클래스에서 넘어오는 id가 각 객체에 자동으로 매겨지는 거죠.

 

이제 이를 누르면 'detail/객체번호'인 url로 넘어가겠죠?

그럼 그 detail.html은 어떤 형태를 띄고 있어야 할까요?

함수에서 가져온 blogdetail로 표현만 해주면 끝~

<h1> {{blogdetail.title}} </h1> 
<p> {{blogdetail.pub_date}} </p>
<p> {{blogdetail.body}}</p>
<a href="{% url 'main' %}">돌아가기</a>

댓글