Python/Django

[Django] Class-Based Views vs Fuction-Based Views

  • -
728x90

https://medium.com/@psychet_learn/djnago-python-django%EB%9E%80-d1165b8e640b

장고 튜토리얼을 진행하면서 view를 작성하는 방법이 두 가지 존재한다는 것을 알게됐다. 아직 장고를 이용해서 많은 프로젝트를 진행해보지 않아서 어떤게 좋고 어떤게 나쁘고는 잘 모르겠지만, 확실한 것은 두가지 방법 모두 자세히 알고 있어야 한다는 것이다.


Class-Based Views vs Fuction-Based Views

Github - Django에 들어가보면
Veiw.as_view() 구성을 확인할 수 있다.

 class View:
    @classonlymethod
    def as_view(cls, **initkwargs):
        """Main entry point for a request-response process."""
        for key in initkwargs:
            # Code omitted for clarity
            # ...

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)

        # Code omitted for clarity
        # ...

        return view

as_view() 메소드에 의해 리턴되는 view함수는 dispatch 메소드에 request를 전달한다. 그러면 dispatch()메소드는 request 타입(GET, POST 등)에 따른 적합한 메소드를 실행한다.

장고 튜토리얼을 진행하며 작성했던 두 코드를 확인해보자.

Function-based Views

urls.py

from django.urls import path

from . import views

app_name = 'polls'

urlpatterns = [
     # ex /polls/
     path('', views.index, name='index'),
     # ex /polls/5/
     path('<int:question_id>/', views.detail, name='detail'),
     # ex /polls/5/results/
     path('<int:question_id>/results/', views.results, name='results'),
     # ex /polls/5/vote/
     path('<int:question_id>/vote', views.vote, name='vote'),
]

veiws.py

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.urls import reverse

from .models import Question, Choice

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context ={ 
        'latest_question_list': latest_question_list,
    }
    return render(request, 'polls/index.html', context)

def detail(request, question_id):
    question = get_object_or_404(Question, pk = question_id)
    return render(request, 'polls/detail.html', {'question':question})

def results(request, question_id):
    question = get_object_or_404(Question, pk = question_id)
    return render(request, 'polls/results.html', {'question': question})

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html',{
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else: 
        selected_choice.votes +=1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

Class-based Views

urls.py


from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    # ex /polls/
    path('', views.IndexView.as_view(), name='index'),
    # ex /polls/5/
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    # ex /polls/5/results/
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    # ex /polls/5/vote/
    path('<int:question_id>/vote', views.vote, name='vote'),
]

veiws.py

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.views import generic

from .models import Question, Choice

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        return Question.objects.order_by('-pub_date')[:5]

class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'

class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html',{
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else: 
        selected_choice.votes +=1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

함수 기반 뷰는 django.veiws.View 클래스를 상속받는 대신, 직접 함수를 작성하여 request를 처리한다. 보통 api_view()로 request 메소드가 무엇인지 명시해주고, 다수의 request 메소드를 사용할 경우 if 조건문으로 구분하여 처리한다.

클래스 기반 뷰는 장고에 제네릭 클래스 기반 뷰라는 강력한 기능이 있다.

제네릭 클래스 기반 뷰는 새로운 객체 생성, 폼 처리, 리스트 뷰, 페이징, 아카이브 뷰 등과 같은 웹 어플리케이션의 일반적인 사용 사례를 해결하기 위해 도입되었다. 이들은 Django 코어에 자리잡아 django.views.generic 모듈에 의해 구현된다. 이 기능은 매우 훌륭하며 개발 프로세스 속도를 높여준다. 사용가능한 뷰들의 목록은 다음과 같다.

Simple Generic Views

- View

- TemplateView

- RedirectView

Detail Views

- DetailView

List Views

- ListView

Editing Views

- FormView

- CreateView

- UpdateView

- DeleteView

Date-Based Views

- ArchiveIndexView

- YearArchiveView

- MonthArchiveView

- WeekArchiveView

- DayArchiveView

- TodayArchiveView

- DateDetailView

Built-in class-based views API

 

Built-in class-based views API | Django documentation | Django

The Django Software Foundation deeply values the diversity of our developers, users, and community. We are distraught by the suffering, oppression, and systemic racism the Black community faces every day. We can no longer remain silent. In silence, we are

docs.djangoproject.com

장단점 비교

함수 기반 뷰

  • 장점: 구현이 간단함, 읽기 편함, 직관적인 코드, 데코레이터 사용이 간단함

  • 단점: 코드를 확장하거나 재사용하기 어려움, 조건문으로 HTTP 메소드 구분

(제네릭) 클래스 기반 뷰

  • 장점: 코드를 확장하거나 재사용하기 쉬움, mixin(다중 상속) 같은 객체지향 기술을 사용할 수 있음, 분리된 메소드로 HTTP 메소드 구분, 내장 제네릭 클래스 기반 뷰

  • 단점: 읽기 힘듦, 직관적이지 않은 코드, 부모 클래스/mixin에 숨어있는 코드들, 뷰 데코레이터를 사용하려면 따로 import를 하거나 메소드를 오버라이드 해야 함수

참조 :
https://yuda.dev/245
https://www.django-rest-framework.org/tutorial/3-class-based-views/
https://simpleisbetterthancomplex.com/article/2017/03/21/class-based-views-vs-function-based-views.html

728x90
300x250
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.