본문 바로가기
개발일지/Django

Django - CBV 방식 시리즈2 (DetailView) 완벽설명이라고 볼수있음

by 개발에정착하고싶다 2022. 12. 31.

#1 개요

 

1)

DetailView도 근본적인 사용방식은 CBV 방식으로써 ListView와 원리적으로는 똑같다.

따라서 구태여 ListView에서 설명된 부분은 생략하고, 실전 코드로 넘어가도록 하겠다.

다만 소개되지 않았지만 새로 발견하게된 부분은 언급하려고 한다.

 

2)

이 CBV 방식은 보아하니 동등한 앱 내에서만 데이터 전송이 가능한것같다.

별도로 지정을 해준다면야 얘기가 달라질 수 있겠지만, 기본세팅으로는

blog앱단위에서 views.py에 상속받아서 사용하는 CBV 방식은 templates/blog/<여기>

에 위치하게 되는 html 파일을 각 CBV 방식에 맞는 인자명으로 데이터셋을 전송하게 되는 구조같다.

 

3)

활용하기에 따라서는 근본적으로 하나의 CBV 방식으로도 모두 사용이 가능한 것 같은데

이름에서 본인의 역할이 무엇인지 말하고 있으니, 각각의 CBV 방식의 이름이 의미하는 대로 사용하는게 좋을것같다.

ListView는 레코드별로 데이터셋을 보내는 역할을 하는 것이고

DetailView는 해당 레코드를 상세하게 보는 역할을 한다고 생각한다.

 

4)

CBV방식의 클래스는 기본적으로 get_context_data 메서드를 내장하고 있다.

상속 이후에 model = <model에서 정의된 클래스명> 이라고 선언하면

get_context_data에서 자동으로 Post 클래스의 경우에는

post_list = Post.objects.all()이라는것과 같은 기능을 한다.


#2 실제 사용코드

 

# blog/models.py
# 이 코드는 ListView 설명에서 변한게 없음

from django.db import models

# Create your models here.
class Post(models.Model):
    title = models.CharField(max_length=30)
    content = models.TextField()

    # auto_now_add는 "최초 저장시"에만 저장이 되고
    created_at = models.DateTimeField(auto_now_add=True)
    # auto_now는 "수정 후 save를 할때마다"최신화 되어 적용된다.
    updated_at = models.DateTimeField(auto_now=True)
    # author 추후 작성 예정

    def __str__(self):
        return f'[{self.pk}]{self.title}'

    # 이것을추가해 줌으로써 admin 페이지에서 볼때는 "View on site"라는 버튼이 생성되었다.
    def get_absolute_url(self):
        return f'/blog/{self.pk}'
# blog/urls.py

from django.urls import path

from . import views

# 이건 각 app 단위의 urls 마다 자동적으로 써주면 좋은 것.
# 중복된 인자명을 배제하기 위해서이다.
# 예를들자면 blog라는 app과 love라는 app에서
# post_list라는 인자를 함께 사용할 경우, 사용에 내가 원하는 결과를 얻을 수 없다.
# app_name을 설정해줌으로 blog:post_list, love:post_list
# 이렇게 <앱이름>:<인자이름> 으로 써주는 것으로 알고있다.
app_name = 'blog'

urlpatterns = [
    path('<int:pk>/', views.PostDetail.as_view())
]
# blog/views.py

from django.views.generic import DetailView

from .models import Post

# Create your views here.
class PostDetail(DetailView):
    model = Post

    # DetailView도 ListView와 마찬가지로 template_name을 
    # 따로 지정해주면 그 파일로,
    # 그렇지 않으면 "post_detail.html"이라는 이름의 파일로 
    # 데이터셋을 보내게 된다.
    # 보통 각 CBV 방식에 대해서 template_name을 따로 지정하지 않으면 
    # "어떤 이름으로 자동배정 되는가"가 궁금하다면, 
    # 일단 실행 했을때 에러 메세지로 나오게 된다.
    # 정확히는 동일한 앱 내에서만 데이터를 보내주는 것 같다.
    # 데이터셋을 전달할때는 ListView와는 약간 다르게 "<클래스명>"이다. 
    # 하지만 클래스명은 파이썬 문법적으로 첫 문자는 대문자로 사용하는 반면, 
    # 전달되는 데이터셋은 대문자가 없는, 이를테면 Post를 model에 지정해줬다면
    # post라는 데이터셋이 post_detail.html이라는 이름의 파일로 가게된다
    # (template_name에 별도로 설정할경우 그곳으로)


    # 에러 메세지
    # TemplateDoesNotExist at /blog/2/
    # blog/post_detail.html

#3 #2의 데이터를 전달받은 결과

 

# templates/blog/post_detail.html

<!doctype html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{ post.title }} - Blog</title<!doctype html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{ post.title }} - Blog</title>
</head>
<body>
<nav>
    <a href="/blog/">Blog</a>
</nav>
<h1>{{ post.title }}</h1>
<h4>{{ post.created_at }}</h4>
<p>{{ post.content }}</p>
<hr>
<h3>comments area</h3>
</body>
</html>>
</head>
<body>
<nav>
    <a href="/blog/">Blog</a>
</nav>
<h1>{{ post.title }}</h1>
<h4>{{ post.created_at }}</h4>
<p>{{ post.content }}</p>
<hr>
<h3>comments area</h3>
</body>
</html>