6번째 줄: |
6번째 줄: |
| 복잡한 코드 없이도 뷰를 손쉽게 만들 수 있다는 장점이 있다. 자동화되어 있다는 것은 좋지만, 구현되지 않은 기능에 대해선 자유도가 떨어진다. | | 복잡한 코드 없이도 뷰를 손쉽게 만들 수 있다는 장점이 있다. 자동화되어 있다는 것은 좋지만, 구현되지 않은 기능에 대해선 자유도가 떨어진다. |
| | | |
| + | 기본적으로 뷰는 함수로 만들지만, 코드가 길어지면 클래스형 뷰가 필요하다. 중급자 이상으로 넘어가기 위해선 필수적으로 숙달해야 할 내용. |
| + | |
| + | 함수형 뷰보다 재사용하기가 쉬워 고급사용자가 될수록 더 많이 사용하게 되는 형태. |
| + | |
| + | 나는 역시 일반적으로 사용하는 기능에 자잘한 기능을 더하게 되어 FBV 방식이 편하다. 그리고 CBV는 탬플릿명 따위가 내정되어 있어, 장고 자체에 대한 이해가 깊지 않으면 오히려 혼란스러운 구조가 된다. |
| === 기본사용 === | | === 기본사용 === |
| | | |
| # <code>from django.views.generic import 필요한뷰</code>형태로 임포트하여 사용한다. | | # <code>from django.views.generic import 필요한뷰</code>형태로 임포트하여 사용한다. |
| # urls.py에서 view를 불러올 때 함수가 아니므로, <code>뷰이름.as_view()</code> 형태로 클래스 내의 메서드를 매칭시켜야 한다. | | # urls.py에서 view를 불러올 때 함수가 아니므로, <code>뷰이름.as_view()</code> 형태로 클래스 내의 메서드를 매칭시켜야 한다. |
| + | View는 기본적으로 함수로 만들지만, 이미 자주 쓰이는 기능을 또 새로이 만들어야 할까? 이미 개발된 뷰가 있다.이를 제네릭뷰라 부르며, 클래스형으로 구성되어 있다. |
| | | |
− | == 제네릭 뷰 ==
| + | 장고에서 제공하는 뷰이다. |
| | | |
− | === ListView === | + | 크게 4가지 분류의 클래스뷰가 있다. CRUD 기능을 제공하게끔. 장고의 특성이다. CRUD 구현이 쉬워.[일반 뷰에서도 이런 틀로 정리해보자.] |
− | 객체목록을 띄우는 뷰. 다음과 같이 사용한다. | + | {| class="wikitable" |
| + | |+ |
| + | !기능 |
| + | !뷰 이름 |
| + | !비고 |
| + | ! |
| + | |- |
| + | |Create |
| + | |CreateView |
| + | |form_class = 사용할 폼이름 |
| + | | |
| + | |- |
| + | |Read |
| + | |DetailView |
| + | | |
| + | | |
| + | |- |
| + | |Update |
| + | |UpdateView |
| + | |기본적으로 CreateView와 같은 속성을 갖는다. |
| + | | |
| + | |- |
| + | |Delete |
| + | |DeleteView |
| + | | |
| + | | |
| + | |}Class형 view가 편하다곤 하지만.. 그 강점은 장고가 업데이트 되 때에 일관성 있게 작동할 가능성을 높여준다는 것 외엔.. 딱히 모르겠다. 사실, 엄청 편리한 것도 모르겠고.. 공부를 위해선, 전체작동방식의 느낌을 알기 위해선 함수를 처음부터 짜는 view가 더 좋은 듯하다.(장고 자체를 더 공부해야 한다는 점에서 별로다; 그럴바엔 파이썬 자체를 더 다뤄보지!) |
| + | |
| + | 내부적으로 어떻게 작동하는지 알기 어려워, 도리어 혼란스러울 때도 있다. |
| + | |
| + | <nowiki>#</nowiki>제네릭 뷰에서 데이터를 탬플릿에 전달할 때 리스트 이름이 지정되어 있는데, 리스트 이름을 바꾸려면 get_queryset함수 안에 이 변수를 넣는다.(글쓰기 기능구현 참조) |
| + | |
| + | context_object_name='바꿀리스트명' |
| + | |
| + | 기본적으로 짧기 때문에 urls.py 안에 바로 기입해줘도 가독성에 무리가 적다. |
| + | |
| + | ==기존 뷰와 다른 점== |
| + | |
| + | === 클래스형 뷰를 사용할 때의 장점 === |
| + | |
| + | * if 함수를 통해 HTTP 메소드를 구분하지 않아도 되서 깔끔하다. def get(self, request): 로 깔끔하게 분리한다. |
| + | * 다중상속이 가능해 믹스인 등을 사용하기 쉽다. 기본적으로 오버라이딩해 사용한다. |
| + | |
| + | 개인적으론... 엄청난 편의성을 제공한다기보단.. 조금 줄여주는 정도로, 나는 오히려 내부의 작동을 한 눈에 알 수 없어 불편하게 느껴진다. |
| + | |
| + | ===url.py 에서 사용할 때=== |
| + | 제네릭 뷰를 사용할 때 urls.py에서 어떤 변수명을 사용하는 게 아니라, 변수명들이 예약되어 있다. |
| + | {| class="wikitable" |
| + | |+예약된 변수명 |
| + | !변수 |
| + | !설명 |
| + | |- |
| + | |<int:pk> |
| + | |기본키를 받아들이는 변수 |
| + | |- |
| + | | |
| + | | |
| + | |- |
| + | | |
| + | | |
| + | |} |
| + | ====함수명 뒤에 .as_view()를 붙인다.==== |
| + | 그냥 view를 사용할 땐 함수명을 쓰면 됬지만, 제네릭 뷰에선 마지막에 .as_view()를 붙여주어야 한다. |
| + | ==제네릭 뷰의 변수== |
| + | {| class="wikitable" |
| + | |+ |
| + | !변수 |
| + | !설명 |
| + | ! 사용예 |
| + | |- |
| + | |success_url |
| + | |함수의 기능이 성공했을 때 어떤 url로 보낼지 지정 |
| + | |success_url='/app/' |
| + | |}self.get_object() : 사용하고 있는 모델의 객체를 가져온다. |
| + | ===함수=== |
| + | 제네릭 뷰 안의 메서드를 정의해 작동한다. |
| + | {| class="wikitable" |
| + | !함수 |
| + | !설명 |
| + | !사용예 |
| + | |- |
| + | |get_success_url |
| + | |성공 후 진행할 작업을 여기에 담는다. |
| + | |<syntaxhighlight lang="python"> |
| + | def get_success_url(self): # 기존 함수를 덧쓴다. 작성 후에 해당 글을 보여주게끔. |
| + | return reverse('pool:detail', kwargs={'pk': self.object.question.pk}) |
| + | </syntaxhighlight> |
| + | |- |
| + | |form_valid |
| + | |폼이 적절할 때 실행할 함수. |
| + | |<syntaxhighlight lang="python"> |
| + | def form_valid(self, form): # 폼에 이상이 없으면 실행. |
| + | temp = form.save(commit=False) # 임시 저장. 폼 외의 다른 내용을 조작하고 싶을 때 사용한다. |
| + | 조작 |
| + | temp.save() # 최종 저장 |
| + | return super().form_valid(form) |
| + | </syntaxhighlight> |
| + | |} |
| + | |
| + | = 제네릭 뷰 = |
| + | |
| + | == ListView == |
| + | 많은 객체들을 한번에 보여주기 위한 뷰. 객체목록을 띄우는 뷰. 다음과 같이 사용한다. |
| {| class="wikitable" | | {| class="wikitable" |
| |+ | | |+ |
27번째 줄: |
135번째 줄: |
| class List(ListView): | | class List(ListView): |
| model = 모델명 # 리스트를 볼 모델을 지정한다. | | model = 모델명 # 리스트를 볼 모델을 지정한다. |
− | template_name = '사용할템플릿명' # 이걸 지정하지 않으면 모델명_list.html 이라는 이름을 가진 템플릿을 매칭한다. | + | context_object_name = '모델을 표현할 이름' # 불러온 모델명을 탬플릿에 보낼 때 그대로 보내는데, 다른 이름을 사용하고 싶을 때 |
| + | template_name = '탬플릿경로' # 이걸 지정하지 않으면 모델명_list.html 이라는 이름을 가진 템플릿을 매칭한다. |
| ordering = '-pk' # 정렬할 속성을 지정한다. '-'를 붙이면 역순으로 정렬한다는 의미. | | ordering = '-pk' # 정렬할 속성을 지정한다. '-'를 붙이면 역순으로 정렬한다는 의미. |
− | </syntaxhighlight> | + | paginate_by = 몇 개 단위로 보여줄 것인가 |
| + | . |
| + | </syntaxhighlight>이렇게 만들면 객체리스트가 <code>모델명_list</code> 형태로 탬플릿에 전달된다. |
| |- | | |- |
| |템플릿 작성 | | |템플릿 작성 |
40번째 줄: |
151번째 줄: |
| </syntaxhighlight> | | </syntaxhighlight> |
| |} | | |} |
− | 이외 다양한 뷰가 있다.
| + | ===pagination=== |
| + | 객체가 너무 많을 때 한 화면에 모든 것을 보여줄 순 없다. 이런 문제를 해결하기 위해 한 화면에 보여줄 객체의 갯수를 정해 페이지화 해야 한다. |
| + | |
| + | 페이지 버튼은 탬플릿에 따로 기입한다. |
| + | |
| + | 다음과 같은 형태로 page 변수를 get 방식으로 넘겨준다.<syntaxhighlight lang="html+django"> |
| + | <a href="{% url '앱:인덱스' %}?page={{ page_obj.number}}">{{ page_obj.number }}</a> |
| + | </syntaxhighlight>페이지 버튼만 따로 떼어 html을 만든 후 include를 하기도 한다. |
| + | |
| + | == DetailView == |
| + | DetailView에선 object라는 변수로 모델이 탬플릿에 전달된다. |
| [[분류:장고 뷰]] | | [[분류:장고 뷰]] |