1)
def item_detail(request, pk):
item = get_object_or_404(Item, pk=pk)
return render(request, 'gallery/item_detail.html',{
'item': item,
})
or
item_detail1 = DetailView.as_view(model=Item)
or
cass ItemDetailView(DetailView):
model = Item
+
item_detail2 = ItemDetailView.as_view()
세 가지 뷰는 거의 동일한 기능을 가진다. 그런데 TemplateView에서는 template_name을 명시적으로 지정해준 반면에 DetailView에서는 모델명과 모델이 위치한 앱 그리고 이것이 DetailView인 점에서 'item_detail'을 유추하는 기능이 내재돼있다.
DetailView가 SingleObjectTemplateResponseMixin을 상속하는데 여기 get_template_names() 메소드가 정의돼있다. suffix가 _detail임을 확인할 수 있다.
item = get_object_or_404(Item, pk=pk)
함수 기반 뷰의 해당 부분은 SingleObjectMixin에 내재돼있다.
2)
class ItemDetailView(DetailView):
model = Item
def get_queryset(self):
qs = super().get_queryset()
if not self.request.user.is_authenticated:
qs = qs.filter(is_public=True)
return qs
로그인하지 않은 유저에게는 is_public의 아이템만 보이도록 코딩한 것인데, 조건을 타이트하게 걸어 줄수록 class 자체를 정의하고 넘어가는 편이 나아 보인다.
3)
템플릿 내에서 사용할 이름은 context라는 사전의 형태로 전달되는데 get_context_data라는 메소드에 정의되길, 모델 인스턴스는 모델의 이름의 소문자 단어뿐만 아니라 object라는 이름으로도 활용할 수 있다.
함수뷰의 render에서 'item'라 정의해준 과정과 유사한 이 부분은 SingleObjectMixin과 View를 상속한 BaseDetailView에서 확인해보자.
4)
ListView는 큰 맥락에서 DetailView와 매우 유사하고 (본 강의에서만 그런지 모르겠지만,) Generic Display View로 묶일 수 있다. 다만 MultipleObject가 포함된 queryset을 반환하는 점과 이를 위해 pagination을 제공한다는 점이 다르다.
paginator가 적용된 queryset을 얻는 부분은 MultipleObjectMixin에 들어있다고 한다.
queryset = object_list if object_list is not None else self.object_list
앞의 'object_list'는 인자로 받은 object_list이고 후자는 클래스 영역에 고정돼서 인스턴스 영역이 받는 'object_list'이다.