Code/Django

url view 추가하기 CBV ( ListView)

하말 ⍺ 2024. 7. 1. 17:13
반응형

FBV Functioon based View ( 뷰에서 함수 씀 )

CBV Class based View ( 뷰에서 클래스 씀)

 

ListView를 이용한 CBV (코드는 gpt를 이용하여 생성했습니다. 설명은 제가 책을 보고 추가)

 

기본 모델 작성

# models.py

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

 

뷰 정의

class 따로 만드는 방법도 있겠지만, 그부분은 아직 학습이 안되어있으니 장고에 기본으로 있는 ListView를 이용한 방법

# views.py

from django.views.generic import ListView, DetailView
from .models import Post

class PostList(ListView):
    model = Post
    template_name = 'blog/post_list.html'
    context_object_name = 'posts'

class PostDetail(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'
    context_object_name = 'post'

 여기서 추가로 집고갈 점은 template_name 지정인데,
기본적으로 ListView는 "모델명_list.html" 파일을 template_name으로 설정한다는 것이다.
마찬가지로 DetailView도 "모델명_detail.html"을 기본 템플릿으로 설정한다.
그러므로 위의 경우 post_list.html과 post_detail.html을 template로 갖는다면

# views.py

from django.views.generic import ListView, DetailView
from .models import Post

class PostList(ListView):
    model = Post
    # template_name = 'blog/post_list.html'
    context_object_name = 'posts'

class PostDetail(DetailView):
    model = Post
    # template_name = 'blog/post_detail.html'
    context_object_name = 'post'

template_name없이 작성해도 문제가 되지 않는다.

 

url 설정

# urls.py

from django.urls import path
from . import views

urlpatterns = [
    # CBV
    path('', views.PostList.as_view(), name='post_list'),
    path('<int:pk>/', views.PostDetail.as_view(), name='post_detail'),
    # FBV
    # path('<int:pk>/', views.single_post_page, name='single_post_page'),
    # path('', views.index, name='index'), # FBV
]

 

html

위에도 적었지만, ListView와 DetailView는 "모델네임_list.html", "모델네임_detail.html"을 기본으로 불러오기 때문에, 이와 다른패턴의 html 을 적용하고자 한다면 views.py의 template_name을 적어줘야한다.

# post_list.html

<!DOCTYPE html>
<html>
<head>
    <title>Post List</title>
</head>
<body>
    <h1>Post List</h1>
    <ul>
        {% for post in posts %}
            <li><a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a></li>
        {% endfor %}
    </ul>
</body>
</html>


# post_detail.html

<!DOCTYPE html>
<html>
<head>
    <title>{{ post.title }}</title>
</head>
<body>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
    <p>Created at: {{ post.created_at }}</p>
</body>
</html>

 

여기서 post_list.html은 for loop을 posts를 갖고 진행했는데
이는 views.py에서 context_object_name 을 설정 했기 때문이다.

만약 context_object_name을 선언하지 않았다면 ListView는 "모델명_list" 혹은 "object_list"를 컨텍스트 변수로 가져온다.

# views.py

from django.views.generic import ListView, DetailView
from .models import Post

class PostList(ListView):
    model = Post
    # template_name = 'blog/post_list.html'
    # context_object_name = 'posts'

class PostDetail(DetailView):
    model = Post
    # template_name = 'blog/post_detail.html'
    context_object_name = 'post'
# post_list.html

<!DOCTYPE html>
<html>
<head>
    <title>Post List</title>
</head>
<body>
    <h1>Post List</h1>
    <ul>
        {% for post in post_list %}
            <li><a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a></li>
        {% endfor %}
    </ul>
</body>
</html>


# post_detail.html

<!DOCTYPE html>
<html>
<head>
    <title>{{ post.title }}</title>
</head>
<body>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
    <p>Created at: {{ post.created_at }}</p>
</body>
</html>

아, DetailView는 컨텍스트를 지정하지 않는다면 모델명을 가져온다. 위의경우엔 post