장고:클래스형 뷰, 제네릭 뷰
장고! 웹 프레임워크! 틀:장고
작정하고 장고의 코드를 참고해 살펴보는 게 좋겠다.
클래스형 뷰
기본적으로 뷰는 함수로 만들지만, 코드가 길어지면 클래스형 뷰가 필요하다. 중급자 이상으로 넘어가기 위해선 필수적으로 숙달해야 할 내용.
함수형 뷰보다 재사용하기가 쉬워 고급사용자가 될수록 더 많이 사용하게 되는 형태.
제네릭 뷰
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 안에 바로 기입해줘도 가독성에 무리가 적다.
제네릭 뷰의 변수
변수 | 설명 | 사용예 |
---|---|---|
fields | 어떤 필드를 기입할지. | fields=['subject', 'text'] |
tempalte_name | 기본 탬플릿 말고 따로 지정할 때 | template_name='app/list.html' |
success_url | 함수의 기능이 성공했을 때 어떤 url로 보낼지 지정 | success_url='/app/' |
model | 어떤 모델에 대한 뷰인지. | model = User |
context_object | 불러온 모델명을 탬플릿에 보낼 때 그대로 보내는데, 다른 이름을 사용하고 싶을 때 | context_object = target_user |
self.get_object() : 사용하고 있는 모델의 객체를 가져온다.
함수
함수 | 설명 | 사용예 |
---|---|---|
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)
|
ListView
많은 객체들을 한번에 보여주기 위한 뷰. 기본 형태는 다음과 같다.
class 뷰이름(ListView):
model = 사용할 모델
context_object_name = '모델을 표현할 이름'
template_name = '탬플릿 경로'
paginate_by = 몇 개 단위로 보여줄 것인가.
이렇게 만들면 객체리스트가 모델명_list
형태로 탬플릿에 전달된다.
pagination
객체가 너무 많을 때 한 화면에 모든 것을 보여줄 순 없다. 이런 문제를 해결하기 위해 한 화면에 보여줄 객체의 갯수를 정해 페이지화 해야 한다.
혹은... infinite scroll 형식으로 만들 수도 있지만 이를 위해선 자바스크립트 사용이 필요하다.
페이지 버튼은 탬플릿에 따로 기입한다.
다음과 같은 형태로 page 변수를 get 방식으로 넘겨준다.
<a href="{% url '앱:인덱스' %}?page={{ page_obj.number}}">{{ page_obj.number }}</a>
페이지 버튼만 따로 떼어 html을 만든 후 include를 하기도 한다.
유의사항
url.py 에서 사용할 때
제네릭 뷰를 사용할 때 urls.py에서 어떤 변수명을 사용하는 게 아니라, 변수명들이 예약되어 있다.
변수 | 설명 |
---|---|
<int:pk> | 기본키를 받아들이는 변수 |
함수명 뒤에 .as_view()를 붙인다.
그냥 view를 사용할 땐 함수명을 쓰면 됬지만, 제네릭 뷰에선 마지막에 .as_view()를 붙여주어야 한다.
탬플릿에서 사용할 때
ListView에선 모델명_list 라는 변수로 탬플릿에 전달된다.
DetailView에선 object라는 변수로 모델이 탬플릿에 전달된다.
Mixin
클래스 뷰를 사용할 때 특정한 기능이 다른 뷰로 분리되어 있을 때. 예컨대, DetailView에선 form이 없기 때문에 댓글을 쓸 수가 없다. 이땐 다중상속을 받아 기능을 구현할 수 있다.
class 뷰이름(DetailView, FormMixin):
form_class = 폼이름
...
def form_valid(self, form):
...
writer = self.request.user
return super().form_valid(form)
위와 같이 Mixin으로 없는 기능을 가져다 넣어 사용할 수 있다.