django view(6) : generic display views

2022. 4. 16. 20:08
  • 인프런 이진석 강사님의 강의를 참고

Generic display views

  • 장고의 CBV중 두번째 카테고리에 속하는 Generic display views
  • DetailView와 ListView가 있음

1.DetailView

 

기능

  • 1개 모델의 1개 Object에 대한 템플릿 처리
  • 모델명의 소문자 이름의 model instance를 템플릿에 전달. 아래 예시에서도 post라는 Post모델의 인스턴스를 템플릿에 전달한다
#views.py
post_detail=DetailView.as_view(model=Post)

 

상속

  • BaseDetailView를 상속받음
    • 얘는 SingleObjectMixin , View를 상속받음
  • SingleObjectTemplateResponseMixin을 직접 상속받음
    • TemplateResponseMixin을 상속받음
    • template_name을 지정할 수 있게 함(즉, 얘를 상속받는 detailview도 그것이 가능하게 함). template_name이 지정되지 않았다면 모델명으로 템플릿 경로 유추
    • url을 통해서 받는 'pk' 혹은 'slug'값으로 필터를 적용하여, 해당 필터에 부합되는(즉 pk값이 맞는)객체 추출
      • 필터에 적용시키는 변수의 이름값이 'pk' 또는 'slug'라고 지정이 되어 있음. 이 이름값을 바꿔주려면 해당 클래스변수명을 바꿔주면 됨
      • 추출한 객체를 obj에 담아서 obj를 리턴
    • get_context_data라는 멤버함수를 가지고 있음
      • 템플릿에서 참조될 수 있는 값들을 context라는 이름의 사전으로 준비해줌
      • 바로 위에서 얘기한 obj를 object라는 이름으로 저장해줌
      • 동시에 obj가 Detailview의 클래스변수인 model의 값으로 주어진 Model의 인스턴스라면(해당 테이블의 한행의 데이터라면), obj를 해당 모델명의 키값으로 사전에 넣어줌
      • ex) Post라는 모델에서, 조건에 부합하는 객체가 있다면, 해당 객체는 'post'라는 키값으로도 접근할 수 있고, 'object'라는 이름으로도 접근할 수 있다.
    • queryset 변수를 가지며, 해당 변수를 활용하여 반환할 (바로 위의)obj에 1차적으로 필터를 걸 수 있음.
      • 해당 변수에 관여하는 멤버함수로 get_queryset이라는 함수가 있음.
      • get_queryset 멤버함수는 만약 queryset이라는 클래스 변수의 값이 비어있다면 ,정된 모델의 모든 객체를 대상으로 pk값 등의 조건에 부합하는 객체를 추출해 낸다.
      • 예를 들어, queryset을 통해 public=true인 값만 obj에 담길 수 있게 하면, pk값이 일치하는 객체라 하더라도 public=false이면 detailview를 통해 템플릿에 전달되지 않음(즉 404 not found가 발생)
      • 또 예를 들어, 로그인이 되어있을 경우에는 모든 post를 볼 수 있고 로그인이 되어있지 않을 때는 게시글들 중 is_public = True인 값만 참조할 수 있게 하는 등의 복잡한 로직을 짜려면 get_queryset함수를 건드려 주는게 편함
#views.py
from .models import Post
from django.views.generic import DetailView

class PostDetailView(DetailView):
    model = Post
    def get_queryset(self):
        qs = super().get_queryset()
        
        if not self.request.user.is_authenticated:#로그인이 되어있지 않다면
            qs = qs.filter(is_public = True)#공개된 것만 봐라
        return qs

post_detail = PostDetailView.as_view()
  • 쿼리셋이 없는 상태에서 super().get_queryset()호출 >> 해당 모델의 모든 객체를 대상으로 하는 qs를 설정
  • 그리고 바로 밑에, 로그인 되어 있지 않다면 is_public = True인 객체들만을 대상으로 하는 qs를 설정
  • 따라서 로그인이 되어있으면 모든 객체의 detailview를 볼 수 있으나, 로그인 되어 있지 않다면 해당 is_public = True인 객체들만의 detailview를 볼 수 있다.

2. ListView

기능

  • 1개 모델에 대한 List템플릿을 처리
  • 모델명의 소문자_list 이름의 쿼리셋을 템플릿에 전달 > 템플릿에서 for문등으로 모델들을 게시할 수 있음
  • 페이징 처리를 지원
#views.py
from django.views.generic import ListView
post_list = ListView.as_view(model=Post,paginate_by=10)

 

상속

  • MultipleObjecttemplateResponseMxixin을 상속받음
    • TemplateResponseMixin을 상속받음
      • template_name을 지정할 수 있게 함(즉, 얘를 상속받는 detailview도 그것이 가능하게 함). template_name이 지정되지 않았다면 모델명으로 템플릿 경로 유추
    • 바로 위 Detailview의 SingleObjectTemplateMixin과 비슷함. 한 개의 객체를 template에 전달하느냐(detailview), 쿼리셋 형태의 여러개의 object를 template에 전달하느냐의 차이일 뿐
      • 근데 이 쿼리셋이 적용된 객체리스트는 바로 밑의 BaseListview의 get함수에 의해 만들어지는 것. 즉 Baselistview에 만들어진 쿼리셋을 Multiple~Mixin 얘가 전달받고, 그걸 템플릿에 전달하는 역할

 

 

 

 

 

  • BaseListview
    • MultipleObjectMixin를 상속받음
      • get함수로 paginator가 적용된 queryset을 획득
      • 해당 queryset을 MultipleobjectTemplateResponseMixin쪽으로 던져줌
      • 쿼리셋에 조건(필터)를 추가하려면 detailview와 동일하게 get_queryset멤버함수를 조정해주면 됨

 

참고)억지로 객체를 늘리는 법

  • 모델의 instance(한 행의 데이터)의 pk = None일 경우, instance.save()는 해당 객체를 모델에 새로이 생성한다
  • 반대로 pk의 값이 있을 경우에는, 해당 객체를 업데이트함
  • 따라서 어떤 객체를 들고와서 pk=none을 주고 save()를 시키면 새로운 객체를 만들어줄 수 있다
#쉘진입 / 모델 import / random함수 import
python manage.py shell
from instagram.models import Post
import random

#객체 전체를 리스트로 담음
post_list = list(Post.objects.all())

#객체 생성
for i in range(100):
	post=random.choice(post_list)
    post.pk=None
    post.save()

 

 

 

 

 

'django > basic' 카테고리의 다른 글

django view(8) : 뷰 장식자(decorator)  (0) 2022.04.16
django view(7) : GenericDateViews  (0) 2022.04.16
django view(5) : view함수를 활용한 json기반의 api통신  (0) 2022.04.16
View(4) CBV : BaseViews  (0) 2022.04.12
View(3) CBV소개  (0) 2022.04.12

BELATED ARTICLES

more