“Django ListView, DetailView로 데이터 조회를 손쉽게 구현하고,
개발 생산성을 극대화해 보세요!”
앞선 글에서 Django의 기본 View 클래스와 FormView를 알아보았다면, 이제는 좀 더 구체적인 제네릭 뷰(Generic Views) 로 나아갈 차례입니다.
ListView와 DetailView는 특히 ‘데이터 출력’ 에 특화된 클래스들이며, 간단한 설정만으로도 목록 페이지와 상세 페이지를 빠르게 구현할 수 있도록 돕습니다.
1. ListView와 DetailView란?
-
ListView
-
모델(Model)에 있는 여러 객체들을 목록 형태로 보여주는 기능을 제공합니다.
-
페이징(Pagination), 정렬, 검색 기능 등을 손쉽게 적용할 수 있어, 대부분의 “목록 페이지”에서 활용할 수 있습니다.
-
-
DetailView
-
특정 객체(예: 게시글, 상품, 사용자 등)의 세부 정보를 표시합니다.
-
URL 파라미터 또는 pk(primary key) 값을 통해 해당 객체를 찾고, 템플릿에서 간단히 렌더링할 수 있습니다.
-
이 두 클래스는 Django가 제공하는 제네릭 뷰의 일부로, CRUD 중 “Read” 역할을 빠르게 구현해 주는 강력한 도구입니다.
2. ListView의 기본 구조와 사용법
2.1 기본 예시
# views.py
from django.views.generic import ListView
from .models import Post
class PostListView(ListView):
model = Post
template_name = 'post_list.html'
context_object_name = 'posts' # 템플릿에서 사용할 컨텍스트 변수명 (기본값: object_list)
# paginate_by = 10 # 페이지당 표시할 개수(선택 사항)
# (선택) 추가적인 쿼리셋 조정이 필요할 때 get_queryset 사용
def get_queryset(self):
# 예: 최신 글만 보여주고 싶다면?
return Post.objects.order_by('-created_at')
-
model
: 어떤 모델의 데이터를 보여줄 것인지 지정합니다. -
template_name
: 템플릿 파일 경로(기본값:<app_name>/<model_name>_list.html
). -
context_object_name
: 템플릿에서 사용할 컨텍스트 객체 이름(기본값:object_list
). -
paginate_by
: 한 페이지에 표시할 객체 수를 지정할 수 있습니다(페이징 처리).
2.2 urls.py에서 ListView 연결하기
# urls.py
from django.urls import path
from .views import PostListView
urlpatterns = [
path('posts/', PostListView.as_view(), name='post_list'),
]
2.3 기본 템플릿 예시
<!-- post_list.html -->
<!DOCTYPE html>
<html>
<head>
<title>게시글 목록</title>
</head>
<body>
<h1>게시글 목록</h1>
<ul>
{% for post in posts %}
<li>
<a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
<!-- 페이징 구현 시 -->
{% if is_paginated %}
<div>
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">이전</a>
{% endif %}
<span>페이지 {{ page_obj.number }} / {{ page_obj.paginator.num_pages }}</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">다음</a>
{% endif %}
</div>
{% endif %}
</body>
</html>
핵심 키워드: “목록 페이지 자동화”, “페이징(Pagination)”, “효율적인 데이터 나열”
3. DetailView의 기본 구조와 사용법
3.1 기본 예시
# views.py
from django.views.generic import DetailView
from .models import Post
class PostDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
context_object_name = 'post' # 템플릿에서 사용할 컨텍스트 변수명 (기본값: object)
# (선택) URL에서 pk가 아닌 다른 식별자를 사용하고 싶다면 get_slug_field 등 오버라이딩 가능
-
model
: 특정 모델의 단일 객체를 조회합니다. -
template_name
: 템플릿 파일 경로(기본값:<app_name>/<model_name>_detail.html
). -
context_object_name
: 템플릿에서 사용할 컨텍스트 객체 이름(기본값:object
). -
URL 패턴에
<int:pk>/
또는<slug:slug>/
등의 패턴이 들어가면 Django가 해당 값을 통해 객체를 자동으로 찾습니다.
3.2 urls.py에서 DetailView 연결하기
# urls.py
from django.urls import path
from .views import PostDetailView
urlpatterns = [
path('posts/<int:pk>/', PostDetailView.as_view(), name='post_detail'),
]
3.3 기본 템플릿 예시
<!-- post_detail.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ post.title }}</title>
</head>
<body>
<h1>{{ post.title }}</h1>
<p>작성일: {{ post.created_at }}</p>
<div>
{{ post.content }}
</div>
<a href="{% url 'post_list' %}">목록으로 돌아가기</a>
</body>
</html>
4. ListView & DetailView 확장하기
4.1 get_queryset, get_context_data
get_queryset()
: 원하는 조건으로 queryset을 커스터마이징할 수 있습니다.
예) 특정 사용자만 볼 수 있는 게시글 목록, 검색어 필터링, 특정 필드 기준 정렬 등.
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(is_active=True)
get_context_data()
: 템플릿에 추가적으로 전달할 데이터를 넣을 수 있습니다.
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['extra_info'] = '추가 정보'
return context
4.2 slug, custom lookup
DetailView는 pk
대신 slug
(짧은 텍스트 식별자)를 사용할 수 있으며, slug_field
, slug_url_kwarg
등을 지정해 커스텀 구성을 할 수도 있습니다.
class PostDetailView(DetailView):
model = Post
slug_field = 'slug' # 모델에 있는 slug 필드명
slug_url_kwarg = 'slug' # URL 패턴에서 받을 파라미터명
4.3 Mixin과의 조합
-
LoginRequiredMixin이나 PermissionRequiredMixin과 함께 사용하면, 목록·상세 페이지에 대한 접근 권한을 손쉽게 제어할 수 있습니다.
-
SearchMixin 같은 커스텀 Mixin을 만들어, 검색어(query) 파라미터를 처리하는 로직을 여러 ListView에서 재활용하는 식으로도 확장 가능합니다.
5. 간단한 실전 예시: 게시판 기능 구현
이전 글에서 다뤘던 예시 모델 Post
를 기준으로, 목록 + 상세를 한번에 구성해보겠습니다.
# models.py
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(unique=True) # slug 사용 예시
def __str__(self):
return self.title
# views.py
from django.views.generic import ListView, DetailView
from .models import Post
class PostListView(ListView):
model = Post
template_name = 'post_list.html'
context_object_name = 'posts'
paginate_by = 5 # 5개씩 페이지 구분
def get_queryset(self):
# slug가 아닌, active 상태인 게시글만 표시한다고 가정
return Post.objects.filter(is_active=True).order_by('-created_at')
class PostDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
context_object_name = 'post'
slug_field = 'slug'
slug_url_kwarg = 'slug'
# urls.py
urlpatterns = [
path('posts/', PostListView.as_view(), name='post_list'),
path('posts/<slug:slug>/', PostDetailView.as_view(), name='post_detail'),
]
-
목록 페이지:
/posts/?page=2
와 같이 페이지 번호를 바꿔가며 목록을 확인할 수 있습니다. -
상세 페이지:
posts/<slug>/
경로를 사용해 특정 게시글을 검색, 템플릿에 표시합니다.
6. FBV와의 비교: 목록/상세를 얼마나 쉽게 구현할 수 있나?
구분 | FBV (함수 기반 뷰) | ListView/DetailView (CBV) |
---|---|---|
코드 구조 | 목록/상세 함수 각각 작성, 페이징·정렬 등은 직접 구현 | 속성 설정만으로 목록, 페이지네이션, 정렬, 검색 등 손쉬운 커스터마이징 가능 |
가독성/유지 보수성 | 조건문, 반복문이 여러 곳에 섞여 프로젝트가 커질수록 복잡해짐 | 목록/상세 로직이 분리되고, 확장(메서드 오버라이딩)이 명확하여 코드 유지 보수가 편리함 |
개발 생산성(핵심 키워드) | “코드 중복 증가, 시간 소모” | “개발 시간을 단축(Time-saving), 생산성 향상(Productivity boost)” |
템플릿 데이터 전달 | 수작업으로 컨텍스트 딕셔너리를 구성해 render에 넘겨야 함 | 기본적으로 컨텍스트(object_list , object )가 자동 전달. 추가 데이터도 간단히 get_context_data 에서 처리 |
페이징, 검색 등 고급 기능 | 별도 로직 작성 필요 | 이미 내장된 기능과 속성으로 쉽게 활성화 가능 |
7. 결론 및 다음 포스트 예고
Django ListView와 DetailView는 “데이터 목록”과 “상세 페이지” 구현을 획기적으로 단순화해 줍니다.
페이징, 컨텍스트 데이터 추가, URL 파라미터에 따른 객체 조회 등 반복적으로 쓰이는 기능을 자동화해 주므로, 코드 재사용성과 개발 생산성에서 큰 이점을 얻을 수 있죠.
CBV(Class-Based View) 시리즈는 계속됩니다!
다음 포스트에서는CreateView
,UpdateView
,DeleteView
를 활용해 손쉽게 CRUD 로직을 구성하는 방법을 살펴보겠습니다.
이전 글 다시 보기
“Django의 ListView, DetailView를 활용해
빠른 데이터 조회, 간편한 개발 그리고 높은 생산성(Productivity)까지 모두 얻어 가세요!”
댓글이 없습니다.