정리
- 각 CBV 동작은 소스코드를 직접 살펴보고 이해해야한다.
- 파이썬 멤버함수 호출순서는 MRO순서를 따른다.[참고]
FBV
def post_edit(request, id):
instance = get_object_or_404(Post, id=id) # Case 1) 인스턴스 획득 조건을 커스텀
if request.method == 'POST':
form = PostForm(request.POST, request.FILES, instance=instance)
if form.is_valid():
post = form.save()
return redirect('/success_url/') # Case 2) 이동할 URL 변경
else:
form = PostForm()
return render(request, 'templates/post_form.html', {'form' : form}) # Case 3) 추가 파라미터 지정
def article_edit(request, id):
# 위 post_edit 뷰와 비슷한 루틴인데, 중복을 최소화하고 재사용성을 어떻게 높일 수 있을까요?
raise NotImplementedError
CBV
클래스 정의
from django.views import View
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponse
class EditFormView(View):
model = None
form_class = None
success_url = None
template_name = None
def get_object(self):
pk = self.kwargs['pk']
return get_object_or_404(self.model, id=pk)
def get_success_url(self):
return self.success_url
def get_template_name(self):
return self.tempate_name
def get_form(self):
form_kwargs = {
'instance' : self.get_object(),
}
if self.request.method == 'POST':
form_kwargs.update({
'date' : self.request.POST,
'files' : self.request.FILES,
# File을 업로드 하기위해 Template에서 Form태그 enctype속성 값을 "multipart/form-data"로 설정해야한다.
})
return self.form_class(**form_kwargs)
def get_context_data(self, **kwargs):
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
return kwargs
def get(self, *args, **kwargs):
return render(self.request, self.get_template_name(), self.get_context_data())
def post(self, *args, **kwargs):
form = self.get_form()
if form.is_valid():
form.save()
return redirect(self.get_success_url())
return render(self.request, self.get_template_name(), self.get_context_data(form=form)
클래스 호출
post_edit = EditFormView.as_view(
model = Post,
form_class = PostForm,
success_url = '/post-success',
template_name = 'blog/post_form.html'
)
# 또는
class PostEditFormView(EditFormView):
model = Post
form_class = PostForm
success_url = '/post-success'
template_name = 'blog/post_form.html'
post_edit = PostEditFormView.as_view()
클래스에 각 인스턴스 함수들을 재정의
from django.shortcuts import resolve_url
class PostEditFormView(EditFormView):
model = Post
form_class = PostForm
template_name = 'blog/post_form.html'
def get_object(self):
pk = self.kwargs['pk']
return get_object_or_404(self.model, id=pk, created_at__year=2018) # 2018년 포스팅 중에서
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['dummy_params'] = '더미 데이터'
return context
def get_success_url(self):
# resolve_url은 urls.py에서 정의한 name을 사용하기 위한 함수
return resolve_url('blog:post_detail', self.kwargs['pk'])
post_edit = PostEditFormView.as_view()