Django에서 뷰를 함수로 작성하는 방식이에요.
# views.py
from django.shortcuts import render
def study_list(request):
studies = Study.objects.all()
return render(request, 'study/list.html', {'studies': studies})
# ❌ FBV
def study_list(request):
studies = Study.objects.all()
return render(request, 'study/list.html', {'studies': studies})
# ✅ CBV
class StudyListView(ListView):
model = Study
template_name = 'study/list.html'
| FBV | CBV | |
|---|---|---|
| 구조 | 함수 | 클래스 |
| 난이도 | 쉬움 | 어려움 |
| 코드량 | 많음 | 적음 |
| 유연성 | 높음 | 낮음 |
from django.shortcuts import render, get_object_or_404
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
특징
if request.method == 'POST':)from django.views import View
class PostDetailView(View):
def get(self, request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
def post(self, request, pk):
# POST 요청 처리
...
특징
CBV를 더 추상화한 것으로, Django가 CRUD 패턴을 미리 구현해 놓은 뷰
from django.views.generic import ListView, DetailView, CreateView
class PostListView(ListView):
model = Post
template_name = 'blog/post_list.html'
context_object_name = 'posts'
class PostDetailView(DetailView):
model = Post
class PostCreateView(CreateView):
model = Post
fields = ['title', 'content']
success_url = '/posts/'
주요 종류
| 클래스 | 용도 |
|---|---|
ListView | 목록 조회 |
DetailView | 단일 객체 조회 |
CreateView | 객체 생성 |
UpdateView | 객체 수정 |
DeleteView | 객체 삭제 |
TemplateView | 단순 템플릿 렌더링 |
| 구분 | 함수뷰 (FBV) | 클래스뷰 (CBV) | 제너릭뷰 |
|---|---|---|---|
| 구조 | 함수 | 클래스 | 클래스 (CBV 확장) |
| 코드량 | 많음 | 중간 | 매우 적음 |
| 가독성 | 직관적 | 구조적 | 선언적 |
| 재사용성 | 낮음 | 높음 | 매우 높음 |
| 유연성 | 매우 높음 | 높음 | 낮음 (커스터마이징 필요) |
| 적합한 경우 | 단순/특수 로직 | 복잡한 로직 | 표준 CRUD |
실무에서는 세 가지를 상황에 맞게 혼용하는 것이 일반적입니다.
FBV
def post_create(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form.save()
return redirect('post_list')
else:
form = PostForm()
return render(request, 'post_form.html', {'form': form})
CBV
class PostCreateView(View):
def get(self, request):
form = PostForm()
return render(request, 'post_form.html', {'form': form})
def post(self, request):
form = PostForm(request.POST)
if form.is_valid():
form.save()
return redirect('post_list')
return render(request, 'post_form.html', {'form': form})
제너릭뷰
class PostCreateView(CreateView):
model = Post
fields = ['title', 'content']
success_url = '/posts/'
# GET/POST 처리, form 생성, 유효성 검사, 저장, 리다이렉트 → 모두 자동
FBV
# 목록
def post_list(request):
posts = Post.objects.all()
return render(request, 'post_list.html', {'posts': posts})
# 상세
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'post_detail.html', {'post': post})
CBV
class PostListView(View):
def get(self, request):
posts = Post.objects.all()
return render(request, 'post_list.html', {'posts': posts})
class PostDetailView(View):
def get(self, request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'post_detail.html', {'post': post})
제너릭뷰
class PostListView(ListView):
model = Post
# Post.objects.all() 자동 실행, 'post_list.html' 자동 탐색
class PostDetailView(DetailView):
model = Post
# pk로 객체 자동 조회, 없으면 404 자동 처리
FBV
def post_update(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == 'POST':
form = PostForm(request.POST, instance=post) # ← instance 직접 넘겨야 함
if form.is_valid():
form.save()
return redirect('post_detail', pk=pk)
else:
form = PostForm(instance=post)
return render(request, 'post_form.html', {'form': form})
CBV
class PostUpdateView(View):
def get(self, request, pk):
post = get_object_or_404(Post, pk=pk)
form = PostForm(instance=post)
return render(request, 'post_form.html', {'form': form})
def post(self, request, pk):
post = get_object_or_404(Post, pk=pk)
form = PostForm(request.POST, instance=post)
if form.is_valid():
form.save()
return redirect('post_detail', pk=pk)
return render(request, 'post_form.html', {'form': form})
제너릭뷰
class PostUpdateView(UpdateView):
model = Post
fields = ['title', 'content']
success_url = '/posts/'
# 기존 데이터 자동 바인딩, 유효성 검사, 저장 모두 자동
FBV
def post_delete(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == 'POST':
post.delete()
return redirect('post_list')
return render(request, 'post_confirm_delete.html', {'post': post})
CBV
class PostDeleteView(View):
def get(self, request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'post_confirm_delete.html', {'post': post})
def post(self, request, pk):
post = get_object_or_404(Post, pk=pk)
post.delete()
return redirect('post_list')
제너릭뷰
class PostDeleteView(DeleteView):
model = Post
success_url = '/posts/'
# 확인 페이지 렌더링 → POST 수신 → 삭제 → 리다이렉트 자동
FBV
요청 → if method == 'POST' 분기 → 직접 폼/쿼리 처리 → 응답
CBV
요청 → dispatch() → get() / post() 자동 분기 → 처리 → 응답
제너릭뷰
요청 → dispatch() → get_object() / get_form() 자동 실행
→ form_valid() / form_invalid() 자동 분기 → 응답
| 핵심 | |
|---|---|
| FBV | 모든 흐름을 내가 직접 작성 |
| CBV | HTTP 메서드 분기를 Django가 처리, 나머지는 직접 |
| 제너릭뷰 | CRUD 흐름 전체를 Django가 처리, 나는 설정만 |