3. 클래스형 뷰

1 개요편집

장고의 뷰는 기본적으로 함수로 만들어진다. 이를 FBV(Function Based View)라 부른다.

이 외에 클래스를 이용하여 기본적인 기능들을 한번에 구현한 CBV(Class Based View)가 있다.(제네릭 뷰라 부르기도 한다.)

복잡한 코드 없이도 뷰를 손쉽게 만들 수 있다는 장점이 있다. 자동화되어 있다는 것은 좋지만, 구현되지 않은 기능에 대해선 자유도가 떨어진다.

기본적으로 뷰는 함수로 만들지만, 코드가 길어지면 클래스형 뷰가 필요하다. 중급자 이상으로 넘어가기 위해선 필수적으로 숙달해야 할 내용.

함수형 뷰보다 재사용하기가 쉬워 고급사용자가 될수록 더 많이 사용하게 되는 형태.

나는 역시 일반적으로 사용하는 기능에 자잘한 기능을 더하게 되어 FBV 방식이 편하다. 그리고 CBV는 탬플릿명 따위가 내정되어 있어, 장고 자체에 대한 이해가 깊지 않으면 오히려 혼란스러운 구조가 된다.

1.1 기본사용편집

  1. from django.views.generic import 필요한뷰형태로 임포트하여 사용한다.
  2. urls.py에서 view를 불러올 때 함수가 아니므로, 뷰이름.as_view() 형태로 클래스 내의 메서드를 매칭시켜야 한다.

View는 기본적으로 함수로 만들지만, 이미 자주 쓰이는 기능을 또 새로이 만들어야 할까? 이미 개발된 뷰가 있다.이를 제네릭뷰라 부르며, 클래스형으로 구성되어 있다.

장고에서 제공하는 뷰이다.

크게 4가지 분류의 클래스뷰가 있다. CRUD 기능을 제공하게끔. 장고의 특성이다. CRUD 구현이 쉬워.[일반 뷰에서도 이런 틀로 정리해보자.]

기능 뷰 이름 비고
Create CreateView form_class = 사용할 폼이름
Read DetailView
Update UpdateView 기본적으로 CreateView와 같은 속성을 갖는다.
Delete DeleteView

Class형 view가 편하다곤 하지만.. 그 강점은 장고가 업데이트 되 때에 일관성 있게 작동할 가능성을 높여준다는 것 외엔.. 딱히 모르겠다. 사실, 엄청 편리한 것도 모르겠고.. 공부를 위해선, 전체작동방식의 느낌을 알기 위해선 함수를 처음부터 짜는 view가 더 좋은 듯하다.(장고 자체를 더 공부해야 한다는 점에서 별로다; 그럴바엔 파이썬 자체를 더 다뤄보지!)

내부적으로 어떻게 작동하는지 알기 어려워, 도리어 혼란스러울 때도 있다.

#제네릭 뷰에서 데이터를 탬플릿에 전달할 때 리스트 이름이 지정되어 있는데, 리스트 이름을 바꾸려면 get_queryset함수 안에 이 변수를 넣는다.(글쓰기 기능구현 참조)

context_object_name='바꿀리스트명'

기본적으로 짧기 때문에 urls.py 안에 바로 기입해줘도 가독성에 무리가 적다.

2 기존 뷰와 다른 점편집

2.1 클래스형 뷰를 사용할 때의 장점편집

  • if 함수를 통해 HTTP 메소드를 구분하지 않아도 되서 깔끔하다. def get(self, request): 로 깔끔하게 분리한다.
  • 다중상속이 가능해 믹스인 등을 사용하기 쉽다. 기본적으로 오버라이딩해 사용한다.

개인적으론... 엄청난 편의성을 제공한다기보단.. 조금 줄여주는 정도로, 나는 오히려 내부의 작동을 한 눈에 알 수 없어 불편하게 느껴진다.

2.2 url.py 에서 사용할 때편집

제네릭 뷰를 사용할 때 urls.py에서 어떤 변수명을 사용하는 게 아니라, 변수명들이 예약되어 있다.

예약된 변수명
변수 설명
<int:pk> 기본키를 받아들이는 변수

2.2.1 함수명 뒤에 .as_view()를 붙인다.편집

그냥 view를 사용할 땐 함수명을 쓰면 됬지만, 제네릭 뷰에선 마지막에 .as_view()를 붙여주어야 한다.

3 제네릭 뷰의 변수편집

변수 설명 사용예
success_url 함수의 기능이 성공했을 때 어떤 url로 보낼지 지정 success_url='/app/'

self.get_object() : 사용하고 있는 모델의 객체를 가져온다.

3.1 함수편집

제네릭 뷰 안의 메서드를 정의해 작동한다.

함수 설명 사용예
get_success_url 성공 후 진행할 작업을 여기에 담는다.
def get_success_url(self):  # 기존 함수를 덧쓴다. 작성 후에 해당 글을 보여주게끔.
    return reverse('pool:detail', kwargs={'pk': self.object.question.pk})
form_valid 폼이 적절할 때 실행할 함수.
def form_valid(self, form):  # 폼에 이상이 없으면 실행.
    temp = form.save(commit=False)  # 임시 저장. 폼 외의 다른 내용을 조작하고 싶을 때 사용한다.
    조작
    temp.save()  # 최종 저장
    return super().form_valid(form)

4 제네릭 뷰편집

4.1 ListView편집

많은 객체들을 한번에 보여주기 위한 뷰. 객체목록을 띄우는 뷰. 다음과 같이 사용한다.

단계 코드
views.py 작성
from django.views.generic import ListView
from models import 모델명  # 리스트를 볼 모델을 불러온다.

class List(ListView):
    model = 모델명  # 리스트를 볼 모델을 지정한다.
    context_object_name = '모델을 표현할 이름'  # 불러온 모델명을 탬플릿에 보낼 때 그대로 보내는데, 다른 이름을 사용하고 싶을 때
    template_name = '탬플릿경로'  # 이걸 지정하지 않으면 모델명_list.html 이라는 이름을 가진 템플릿을 매칭한다.
    ordering = '-pk'  # 정렬할 속성을 지정한다. '-'를 붙이면 역순으로 정렬한다는 의미.
    paginate_by =   단위로 보여줄 것인가
    .
이렇게 만들면 객체리스트가 모델명_list 형태로 탬플릿에 전달된다.
템플릿 작성
<!---->

{% for post in 모델명_list %} <!--객체들이 모델명_list 안에 담겨 순회한다.-->
...
{% endfor %}

4.1.1 pagination편집

객체가 너무 많을 때 한 화면에 모든 것을 보여줄 순 없다. 이런 문제를 해결하기 위해 한 화면에 보여줄 객체의 갯수를 정해 페이지화 해야 한다.

페이지 버튼은 탬플릿에 따로 기입한다.

다음과 같은 형태로 page 변수를 get 방식으로 넘겨준다.

<a href="{% url '앱:인덱스' %}?page={{ page_obj.number}}">{{ page_obj.number }}</a>

페이지 버튼만 따로 떼어 html을 만든 후 include를 하기도 한다.

4.2 DetailView편집

DetailView에선 object라는 변수로 모델이 탬플릿에 전달된다.