WeniVooks

검색

Django 베이스캠프

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는 다음과 같은 순서로 동작합니다.

  1. 지정된 템플릿 파일을 로드합니다.
  2. 전달된 context 딕셔너리를 사용자 요청인 request와 함께 템플릿에 적용합니다.
  3. 렌더링된 템플릿을 문자열로 변환합니다.
  4. 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
2.3 URL 추가 설명2.5 템플릿 태그 추가 설명