View 추가 설명
1. View 소개
Django에서 View는 두뇌 역할을 하게 됩니다. 해당 URL로 사용자가 들어오게 되면 View는 사용자의 요청을 받아 처리하고, 그 결과를 사용자에게 보여주는 역할을 합니다. 필요한 데이터가 있을 경우에는 DB에서 데이터를 읽어와 처리하고, 비즈니스 로직이 필요한 경우에는 해당 로직을 작성하여 처리할 수 있습니다. 비즈니스 로직이란 로그인, 회원가입, 게시글 작성, 수정, 삭제 등과 같은 웹사이트의 핵심 기능을 의미합니다. View는 이러한 비즈니스 로직을 처리하고, 결과를 사용자에게 보여주는 역할을 합니다.
이 수업은 배우지 않은 내용도 상당부분 포함되어 있어 실습을 진행하지 않습니다. 하지만 Django를 배울 때 왜 이러한 코스로 설계가 되었는지를 이해하는데 도움이 될 것입니다.
1.1 함수형 View와 클래스형 View
Django에서는 두 가지 유형의 View를 사용할 수 있습니다. 함수형 View와 클래스형 View입니다.
1.1.1 함수형 View
함수형 View는 가장 기본적이고, 직관적이며, 이해하기 쉬워 초보자들이 Django를 배우기 시작할 때 흔히 접하는 형태입니다. 베이스캠프 강의는 대부분 이 함수형 View를 기반으로 합니다. 함수형 View는 HTTP 요청 객체를 인자로 받아 HTTP 응답 객체를 반환합니다. 간단한 로직부터 복잡한 처리까지 다양한 상황에 사용할 수 있으며 대부분의 기능이 추상화 되어 있는 클래스형 View에 비해 코드를 이해하기 쉽다는 장점이 있습니다. 아래는 함수형 View의 간단한 예시입니다.
# urls.py
from django.urls import path
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello, World!")
urlpatterns = [
path('hello/', hello_world),
]
# urls.py
from django.urls import path
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello, World!")
urlpatterns = [
path('hello/', hello_world),
]
1.1.2 클래스형 View
클래스형 View는 View를 만드는 또 다른 방법입니다. 함수 대신 클래스를 사용하여 View를 정의합니다. 이미 추상화되어 있는 여러 기능을 통해 코드를 더 간결하게 작성할 수 있습니다. 이를 이용해 코드의 재사용성을 높일 수 있습니다. 다만 클래스형 View는 함수형 View에 비해 코드가 추상화 되어 있어 초보자들이 이해하기 어려울 수 있습니다. 하지만 실무에서 많이 사용하며, Django에서 제공하는 여러 기능을 활용할 수 있습니다.
View 클래스는 \venv\Lib\site-packages\django\views\generic\base.py
에 정의되어 있습니다. 다른 클래스형 View를 사용할 때는 이 클래스를 상속받아 사용합니다. 아래는 클래스형 View의 가장 기본적인 예시입니다.
# urls.py
from django.urls import path
from django.views import View
from django.http import HttpResponse
class HelloWorldView(View):
def get(self, request):
return HttpResponse("안녕하세요!")
urlpatterns = [
path('hello/', HelloWorldView.as_view()),
]
# urls.py
from django.urls import path
from django.views import View
from django.http import HttpResponse
class HelloWorldView(View):
def get(self, request):
return HttpResponse("안녕하세요!")
urlpatterns = [
path('hello/', HelloWorldView.as_view()),
]
위 예시에서 HelloWorldView 클래스는 GET 요청이 오면 "안녕하세요!"라고 응답합니다. 좀 더 복잡한 로직에서는 generic view를 사용하여 더 간결하게 코드를 작성할 수 있습니다. 여기서 모델이란 앞에서 정의했었던 리스트 안에 딕셔너리 형태의 블로그 데이터 전체라고 생각해주시면 됩니다.
ListView는 \venv\Lib\site-packages\django\views\generic\list.py
에 정의 되어 있습니다. ListView는 BaseListView를 상속받고, BaseListView는 View를 상속받습니다. 따라서 ListView는 View를 상속받아 추가 기능을 구현하여 사용하는 것입니다.
from django.views.generic import ListView
from .models import Blog
class BlogListView(ListView):
model = Blog
template_name = 'blog/blog_list.html'
context_object_name = 'blog_list'
from django.views.generic import ListView
from .models import Blog
class BlogListView(ListView):
model = Blog
template_name = 'blog/blog_list.html'
context_object_name = 'blog_list'
위와 같이 사용하면 자동으로 Blog모델 전체를 가져와서 blog_list.html
에서 사용할 수 있도록 준비해줍니다. 심지어 template_name이 없어도 모델명으로 blog_list.html
을 자동 매핑 합니다. context_object_name
도 만약 값이 없다면 object_list
로 자동 매핑합니다. 그러니 최종적으로는 아래와 같이 사용이 가능한겁니다.
from django.views.generic import ListView
from .models import Blog
class BlogListView(ListView):
model = Blog
from django.views.generic import ListView
from .models import Blog
class BlogListView(ListView):
model = Blog
이 코드를 함수형 View로 작성하려면 아래와 같이 작성해야 합니다.
from django.shortcuts import render
from .models import Blog
def blog_list(request):
blogs = Blog.objects.all()
return render(request, 'blog/blog_list.html', {'blog_list': blogs})
from django.shortcuts import render
from .models import Blog
def blog_list(request):
blogs = Blog.objects.all()
return render(request, 'blog/blog_list.html', {'blog_list': blogs})
따라서 처음에는 함수형 View보다 직관적이지 않아 어색할 수 있지만, 큰 프로젝트를 할 때 코드를 더 체계적으로 관리할 수 있게 해줍니다.
1.2 render 함수
Django의 render()
함수는 HttpResponse 객체를 생성하는 편리한 방법을 제공합니다. 이 함수는 템플릿을 로드하고, 컨텍스트를 적용하여 렌더링한 후, HttpResponse 객체로 결과를 반환합니다. \venv\Lib\site-packages\django\shortcuts.py
파일에서 return되는 값을 확인해보세요. render에서 사용되는 render_to_string 함수는 텍스트를 읽어와서 렌더링한 후 문자열로 반환하는 함수입니다.
1.2.1 render 함수의 기본 구조
render(request, template_name, context=None, content_type=None, status=None, using=None)
render(request, template_name, context=None, content_type=None, status=None, using=None)
request
: 현재 요청 객체입니다.template_name
: 사용할 템플릿의 이름입니다.context
: 템플릿에 전달할 데이터 딕셔너리입니다. (기본값: None)content_type
: 결과 문서의 MIME 타입입니다. (기본값: 'text/html')status
: 응답의 상태 코드입니다. (기본값: 200)using
: 사용할 템플릿 엔진의 이름입니다. Django의 기본 템플릿 엔진을 사용할 때는 None으로 설정합니다. 지원하고 있는 템플릿 엔진으로는 Django 템플릿 엔진, Jinja2, Mako가 있습니다. (기본값: None)
1.2.2 render 함수의 동작 과정
render는 다음과 같은 순서로 동작합니다.
- 지정된 템플릿 파일을 로드합니다.
- 전달된
context
딕셔너리를 사용자 요청인request
와 함께 템플릿에 적용합니다. - 렌더링된 템플릿을 문자열로 변환합니다.
- HttpResponse 객체를 생성하고 렌더링된 문자열을 담아 반환합니다.
1.2.3 render 함수의 동작 예시
# render_to_string 사용하여 render원리 파악
from django.template.loader import render_to_string
from django.http import HttpResponse
def hello_world(request):
rendered = render_to_string("hello.txt", {"name": "Django"})
print(rendered)
print(type(rendered))
name = "hojun"
s = f"<br/>hello, {name}"
return HttpResponse(rendered + s)
# render_to_string 사용하여 render원리 파악
from django.template.loader import render_to_string
from django.http import HttpResponse
def hello_world(request):
rendered = render_to_string("hello.txt", {"name": "Django"})
print(rendered)
print(type(rendered))
name = "hojun"
s = f"<br/>hello, {name}"
return HttpResponse(rendered + s)
위 코드는 hello.txt
템플릿을 렌더링한 결과를 출력합니다. hello.txt
템플릿은 아래와 같이 작성되어 있습니다.
Hello, {{ name }}!
Hello, {{ name }}!
그러니 실제로 render는 html파일을 html파일로 읽어오는 것이 아니라 문자열로 받아서 렌더링한 후 문자열로 반환하는 것입니다.
Django 공식 문서- render