[Django] 장고 View
함수 기반 View
함수 기반 View, 즉, View함수는 우리가 지금까지 다뤘던 글에서 보았던 View함수를 의미한다. 서비스를 처리하고 다시 응답하는 프로세스를 가진다. 보통 urls.py에서 path를 지정하고 해당 path를 요청했을 때 해당 View함수가 실행되는 로직으로 짜여져있다.
클래스 기반 View
클래스 기반의 View에서는 View 클래스 내부에 여러가지 서비스 처리부터 요청을 받고 응답을 하는 모든기능이 포함된 함수들을 가진다.
위처럼 View 클래스는 get, post기능을 하는 각기 다른 함수들을 포함한다. 이 부분은 어떤 View 클래스냐에 따라 다르다.
장고에서는 미리 이렇게 사용할 수 있는 클래스들을 정의하고 사용자들에게 간편하게 가져다 쓸 수 있도록 documentation과 API를 제공한다.
Django Class-Based-View Inspector -- Classy CBV
What are class-based views anyway? Django's class-based generic views provide abstract classes implementing common web development tasks. These are very powerful, and heavily-utilise Python's object orientation and multiple inheritance in order to be exten
ccbv.co.uk
위 페이지 링크에 접속하면 다양한 View함수들을 가져다 쓸 수 있으며, 커스터마이징을 통해 해당 클래스를 상속받아서 일부 기능을 변경할 수도 있다.
제너릭 뷰 (Generic View)
위에서 클래스 기반으로 View를 사용하되 이미 장고에서 제공하는 View 클래스들을 제너릭 뷰라고 한다. 마찬가지로 위 사이트 링크에 접속해보면 다양한 제너릭 뷰를 지원한다.
제너릭 뷰의 클래스 변수를 수정하는 방법은 2가지가 있다.
- as_view() 메서드의 키워드 인자로 지정하는 방법
- 제너릭 뷰를 상속받은 클래스에서 지정하는 방법
as_view() 메서드의 키워드 인자로 지정하는 방법
as_view 메서드의 키워드 인자로 지정하는 방법은 수정 방법이 매우 단순하기 때문에 대개는 따로 views.py에 정의하지 않고 장고에서 제공하는 패키지에서 가져와 urls.py의 path에 그대로 작성한다.
위 예시에서는 제너릭 뷰 종류 중 ListView라는 View클래스 as_view 메서드에 'model=book'이라는 옵션을 주어서 Book이라는 모델에 대해서 List를 짜주는 View를 호출한 것이다.
제너릭 뷰를 상속받은 클래스에서 지정하는 방법
위 예시와 동일하지만 제너릭 뷰 클래스를 상속받은 뷰 클래스를 정의하는 방법이다.
위 처럼 views.py에 새로운 내가 정의한 View 클래스에 제너릭 뷰를 상속받고 정의한 View 클래스에서 필요한 부분만 추가한다.
ListView
제너릭 뷰 중 ListView는 위에서 다뤘던 예시처럼 model 변수에 지정된 model의 모든 인스턴스들을 추출해서 템플릿의 context로 전달하는 view이다.
ListView 클래스를 사용하게 되면 자동적으로 '모델명소문자_list.html' 템플릿을 찾도록 되어있고 이 템플릿에 지정된 model의 모든 인스턴스들을 context로 넘기게 된다. 위의 예시에서 처럼 Book이라는 모델을 인자로 넣어주면 Book 모델의 모든 인스턴스가 html 템플릿 파일의 context로 넘어가서 장고 반복문 태그를 통해 각각 인스턴스 정보가 표시된다.
DetailView
DetailView는 장고에서 정의한 model의 인스턴스 중 해당되는 인스턴스의 자세한 정보를 보여주는 서비스를 실행해준다.
ListView와 마찬가지로 urls.py에서 DetailView 클래스가 실행되도록 해당 path에 사용자가 접속하면 DetailView 클래스는 '모델명소문자_detail.html' 템플릿을 찾고 context를 넘기며 실행한다.
CreateView
CreateView는 model의 인스턴스 생성, 즉, 추가 기능이 구현된 제너릭 뷰이다. CreateView는 장고의 Form을 기반으로 작동된다.
CreateView는 반드시 생성할 인스턴스의 model을 지정해줘야하며 이 model을 기반으로 새로운 DB를 추가한다.
form_class를 사용자 정의에 따라 설정할 수 있다. 지정하지 않으면 default로 ModelForm이 자동으로 생성된다. 이 ModelForm은 지정한 model을 기반으로 만들어진다.
그 이외에도 여러가지 기본 속성들이 있다.
- template_name : GET 방식 또는 Form의 유효성 검사 실패시 응답할 template 지정 (기본 template name은 '모델명소문자_form.html' 이다.)
- success_url : POST 방식으로 요청되어 데이터 추가 작업이 완료된 후 이동할 URL을 지정한다. 지정하지 않으면 지정해줬던 model의 get_absolute_url() 메서드가 반환하는 URL로 이동.
- fields : 별도의 form을 지정하지 않고 모델 기반의 ModelForm을 생성하여 사용할 때 Form의 필드로 사용할 모델 필드 지정. → 작성할 field를 지정해줄 수 있다. (예를 들어, default로 생성되는 field는 입력받지 않는다던가, 중요한 field만 입력받는 식으로 form을 구성해줄 수도 있다.)
CreateView 동작 방식
- GET 방식으로 CreateView가 실린 path가 요청되면 GET에 해당되는 template를 응답해준다. (기본 : '모델명소문자_form.html')
- 사용자는 폼에 추가할 모델 인스턴스의 데이터를 입력하고 submit 버튼을 누르면 POST 방식으로 요청된다.
- CreateView가 다시 POST 방식으로 요청받았으므로 입력 받은 값을 Form 객체에 바인딩하고 유효성 검사를 진행한다.
- 유효성 검사에서 성공하게 되면 입력값을 DB에 추가하고 success_url에 지정된 URL로 이동시킨다.
- 유효성 검사에 실패하게 되면 오류 메시지와 함께 기존의 GET 요청방식 입력 페이지로 다시 이동시킨다.
CreateView의 Form 사용
GET 방식으로 URL이 요청되었을 때 CreateView는 지정된 Form을 템플릿에 넘기게 되고 해당 form은 as_table, as_p 등의 방법으로 템플릿에 표시된다.
UpdateView
UpdateView는 CreateView와 아주 흡사한 제너릭 뷰이다. 다만 이미 생성된 model 인스턴스에 대해서 수정작업을 거쳐야하기 때문에 이미 생성된 인스턴스를 가져와야 한다.
GET 방식 요청시
UpdateView는 GET방식으로 요청할 때 PK(기본키)값을 받게 된다. 이 PK값으로 먼저 model 객체 인스턴스를 받아오고 Form에 바인딩을 한다. 그리고 해당되는 template(모델명소문자_form.html)을 응답하면서 context로 인스턴스를 넘긴다.
이렇게 되면 Form에는 PK로 추출되었던 인스턴스 객체의 값들의 바인딩된 값들이 초기값으로 출력된다.
POST 방식 요청시
GET 방식으로 요청하고 Form을 받은 사용자는 일부 속성값을 수정한 뒤 submit 버튼을 누르면 POST 요청을 하게 된다.
POST 방식 요청을 받은 UpdateView는 입력받은 값을 Form 객체에 바인딩하고 유효성 검사를 진행한다. 이 부분은 CreateView와 완전히 동일하다.
DeleteView
DeleteView는 데이터 삭제 기능을 구현한 제너릭 뷰이다. CreateView, UpdateView와 흡사하게 model을 필수로 지정해야하며 success_url과 template_name을 지정해줄 수 있다.
GET 방식 요청시
DeleteView 응답은 사실상 하나와 다름없다. 삭제를 원하는 PK와 함께 URL로 GET 방식 요청이 들어오면 삭제 작업을 계속할 것인지 묻는 템플릿을 응답한다. (템플릿 기본 이름은 '모델명소문자_confirm_delete.html'이다.)
POST 방식 요청시
삭제를 계속할 것인지 묻는 템플릿에서 사용자가 계속 진행을 원한다면 yes 아니라면 no를 submit하게 되는데 이를 POST요청으로 받아들여 yes라면 해당 인스턴스 삭제를 진행하고 success_url을 응답한다. no을 요청받았으면 이전의 페이지를 응답하거나 다른 방식으로 응답할 수 있다.
reverse vs reverse_lazy
위 DeleteView에서 reverse_lazy라는 놈이 나왔다. 왜 계속 reverse를 사용하다가 뜬금없이 reverse_lazy를 썼을까?
일단 위 코드에서 reverse_lazy 대신 reverse를 사용하면 오류가 발생한다.
그 이유는 python, 장고가 실행될 때 python 코드들은 evaluate하는 과정에서 발생한다.
장고는 실행될 때 관련된 python 코드들을 evaluate하는 과정을 거치는데 이때 url이 정의되기 전에 먼저 클래스 내부에서 reverse로 url path를 정의한 것이 있다면 python은 이 path가 어딘지 장고에게 설명할 수가 없다.
때문에 클래스의 내부 변수로 사용될 때는 일반 reverse가 아닌 reverse_lazy를 사용해야 한다.
다만 클래스 내부 함수안에서 url을 선언할 때는 일반 reverse를 사용해도 무방하다.
https://yuuraa.github.io/djange/reverse_lazy/python/django-reverse-lazy/
Django의 reverse_lazy vs. reverse
Django urls의 함수들 Django에서는 url을 편안하게 사용할 수 있는 기능을 제공한다
yuuraa.github.io
(설명이 아주 잘 되어있다. 제 설명이 빈약해서 첨부합니다.)
reference
https://ccbv.co.uk/projects/Django/4.1/django.views.generic.edit/CreateView/
CreateView -- Classy CBV
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] View
ccbv.co.uk
https://yuuraa.github.io/djange/reverse_lazy/python/django-reverse-lazy/
Django의 reverse_lazy vs. reverse
Django urls의 함수들 Django에서는 url을 편안하게 사용할 수 있는 기능을 제공한다
yuuraa.github.io