4 minute read

클래스형 뷰

개발자들이 자주 쓸만한 뷰를 클래스로 만들어 둔 것을 클래스형 뷰라고 한다.

def post_create(request):
    if request.method == 'POST':
        post_form = PostForm(request.POST)
        if post_form.is_valid():
            new_post = post_form.save()
            return redirect('post-detail', post_id=new_post.id)
    else:
        post_form = PostForm()
    return render(request, 'posts/post_form.html', {'form':post_form})

기존의 함수형 뷰를 클래스형 뷰로 수정해보면

from django.views import View

class PostCreateView(View):
    def get(self, request):
        post_form = PostForm()
        return render(request, 'posts/post_form.html', {'form':post_form})

    def post(self, request):
        post_form = PostForm(request.POST)
        if post_form.is_valid():
            new_post = post_form.save()
            return redirect('post-detail', post_id=new_post.id)
        return render(request, 'posts/post_form.html', {'form': post_form})

이렇게 상속을 받아서 편하게 작성할 수 있다.
그리고 urls에서는
path(‘posts/new’, views.PostCreateView.as_view(), name=’post-create’)
이렇게 .as_view()를 붙여줘야 한다.

제네릭 뷰

개발자들이 자주 쓸만한 뷰를 하나의 형태로 만들어 둔 것을 제네릭 뷰라고 한다.

CreateView

from django.views.generic import CreateView
from django.urls import reverse

class PostCreateView(CreateView):
    model = Post
    form_class = PostForm
    template_name = 'posts/post_form.html'

    def get_success_url(self):
        return reverse('post-detail', kwargs={'post_id': self.object.id})

이런식으로 사용하면 된다.
정상적으로 작성이 됐을 때 페이지를 이동하도록 get_success_url을 만든다.
reverse함수는 url-name으로 이용한 실제 url을 리턴한다. 이 때 필요한 키워드를 kwargs파라미터로 전달할 수 있다.

urls에서 as_view를 사용하도록 수정한다.

ListView

def post_list(request):
    posts = Post.objects.all()
    paginator = Paginator(posts, 6)
    curr_page_number = request.GET.get('page')
    if curr_page_number is None:
        curr_page_number = 1
    page = paginator.page(curr_page_number)
    return render(request, 'posts/post_list.html', {'page': page})

기존에 이렇게 작성했던 것을

from django.views.generic import ListView

class PostListView(ListView):
    model = Post
    template_name = 'posts/post_list.html'
    context_object_name = 'posts'
    ordering = ['-dt_created']
    paginate_by = 6
    page_kwargs = 'page'

이렇게 수정하면 된다.

page_kwarg는 쿼리 스트링으로 부터 현재 페이지에 대한 번호를 가져올 때 사용할 키워드를 적어주는 부분이다.

context_object_name은 뷰에서 컨텍스트 변수명을 별도로 정해준다.
사용하지 않으면 object_list변수에 객체를 할당하게 된다.

urls에서 as_view를 사용하도록 수정하고

템플릿에서는 기존에는 page키워드로 받았던 것을 page_obj키워드로 받도록 수정한다. 제네릭 ListView는 페이지네이션을 적용해서 각각의 페이지를 page_obj라는 context로 전달하기 때문이다.

DetailView

def post_detail(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    context = {"post":post}
    return render(request, 'posts/post_detail.html', context)

기존의 방식에서

from django.views.generic import DetailView

class PostDetailView(DetailView):
    model = Post
    template_name = 'posts/post_detail.html'
    pk_url_kwarg = 'post_id'
    context_object_name = 'post'

이렇게 수정하면 된다.
pk_url_kwarg는 urls.py에서 URL 패턴에 있는 데이터를 조회할 키워드의 이름을 적어주는 부분이다.

UpdateView

def post_update(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    if request.method == 'POST':
        post_form = PostForm(request.POST, instance=post)
        if post_form.is_valid():
            post_form.save()
            return redirect('post-detail', post_id=post.id)
    else:
        post_form = PostForm(instance=post)
    return render(request, 'posts/post_form.html', {'form': post_form})

기존의 코드에서

from django.views.generic import UpdateView

class PostUpdateView(UpdateView):
    model = Post
    form_class = PostForm
    template_name = 'posts/post_form.html'
    pk_url_kwarg = 'post_id'

    def get_success_url(self):
        return reverse('post-detail', kwargs={'post_id': self.object.id})

이렇게 수정

DeleteView

def post_delete(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    if request.method == 'POST':
        post.delete()
        return redirect('post-list')
    else:
        return render(request, 'posts/post_confirm_delete.html', {'post': post})

기존의 코드

class PostDeleteView(DeleteView):
    model = Post
    template_name = 'posts/post_confirm_delete.html'
    pk_url_kwarg = 'post_id'
    context_object_name = 'post'

    def get_success_url(self):
        return reverse('post-list')

수정된 코드
404처리까지 자동으로 된다.

제네릭 뷰 context

템플릿으로 전달되는 model데이터

ListView -> ‘object_list’, ‘[모델명]_list’
DetailView -> ‘object’, ‘[모델명]’
CreateView -> 없음
UpdateView -> ‘object’, ‘[모델명]’
DeleteView -> ‘object’, ‘[모델명]’

context_object_name을 설정하면 값이 변경되어서 넘어간다.

ListView에서 context_obejct_name = ‘page’라고 했으면 ‘object_list’와 ‘page’ 두가지가 넘어가게 된다.

ListView에서 템플릿으로 전달하는 context

  • paginator
    페이지네이션을 적용하면 장고에서 제공하는 페이지네이터 객체가 전달된다.
    기본값으로는 None으로 페이지네이션이 적용되어 있지 않다.
    페이지네이션을 적용하려면 리스트뷰에서 pageinated_by를 작성해야 한다.

  • page_obj
    페이지네이션을 적용하면 현재 Page객체가 전달된다.

  • is_paginated
    기본값은 False이고 페이지네이션을 적용하면 True가 된다.

  • object_list, [모델명]_list
    현재 Page에 있는 데이터 목록이 전달된다.

제네릭 뷰 정리

  • Base Views
    • TemplateView
      template_name -> 렌더할 템플릿을 지정하는 속성: None

    • RedirectView
      url -> 이동할 url을 지정하는 속성, 기본값: None
      pattern_name -> url패턴의 이름을 지정하는 속성, 기본값: None
      query_string -> 쿼리 스트링을 전달할 지 여부, 기본값: False

  • Display Views
    • ListView
      model -> 사용할 모델 지정, 기본값: None
      ordering -> 데이터 정렬 속성 지정, 기본값: None
      paginate_by -> 페이지에 표시 할 데이터의 수, 기본값: None
      page_kwarg -> 쿼리스트링으로부터 가져올 현재 페이지에 대한 키워드, 기본값: ‘page’
      template_name -> 렌더할 템플릿을 지정하는 속성, 기본값: None
      context_object_name -> 템플릿으로 전달할 모델의 context 키워드 지정, 기본값: ‘[model_name]_list’

    • DetailView
      model -> 사용할 모델 지정, 기본값: None
      pk_url_kwarg -> urls.py에서 지정한 키워드 인수, 기본값: ‘pk’
      template_name -> 렌더할 템플릿을 지정하는 속성, 기본값: None
      context_object_name -> 템플릿으로 전달할 모델의 context 키워드 지정, ‘[model_name]’

  • Edit Views
    • FormView
      form_class -> 입력을 위한 Form Class를 지정, 기본값: None
      success_url -> 처리가 성공했을 때 리디렉션 할 URL을 지정, 기본값: None
      template_name -> 렌더할 템플릿을 지정하는 속성, 기본값: None

    • CreateView
      model -> 사용할 모델 지정, 기본값: None
      form_class -> 입력을 위한 Form Class를 지정, 기본값: None
      fields -> 데이터 입력에 사용할 필드를 명시적으로 지정, 기본값: None
      template_name -> 렌더할 템플릿을 지정하는 속성, 기본값: None
      pk_url_kwarg -> urls.py에서 지정한 키워드 인수, 기본값: ‘pk’
      success_url -> 처리가 성공했을 때 리디렉션 할 URL을 지정, 기본값: None

    • UpdateView
      model -> 사용할 모델 지정, 기본값: None
      form_class -> 입력을 위한 Form Class를 지정, 기본값: None
      fields -> 데이터 입력에 사용할 필드를 명시적으로 지정, 기본값: None
      template_name -> 렌더할 템플릿을 지정하는 속성, 기본값: None
      pk_url_kwarg -> urls.py에서 지정한 키워드 인수, 기본값: ‘pk’
      success_url -> 처리가 성공했을 때 리디렉션 할 URL을 지정, 기본값: None
      context_object_name -> 템플릿으로 전달할 모델의 context 키워드 지정, 기본값: ‘[model_name]’

    • DeleteView
      model -> 사용할 모델 지정, 기본값: None
      template_name -> 렌더할 템플릿을 지정하는 속성, 기본값: None
      pk_url_kwarg -> urls.py에서 지정한 키워드 인수, 기본값: ‘pk’
      success_url -> 처리가 성공했을 때 리디렉션 할 URL을 지정, 기본값: None
      context_object_name -> 템플릿으로 전달할 모델의 context 키워드 지정, 기본값: ‘[model_name]’

  • Date Views
    • YearArchiveView
    • MonthArchiveView
    • DayArchiveView
    • TodayArchiveView

context

Context는 View에서 Template으로 전달되어 렌더링시 사용할 수 있는 사전형 데이터 변수다.
render함수에서 세번째 파라미터로 사용했던 부분이다.

  • CreateView
    • form -> form_class 클래스 변수에 명시한 폼이 전달된다.
  • ListView
    • paginator -> Paginator 객체가 전달된다.
    • page_obj -> 현재 Page 객체가 전달된다.
    • is_paginated -> 페이지네이션 적용 여부가 boolean 형으로 전달된다.
  • UpdateView
    • form -> form_class 클래스 변수에 명시한 폼이 전달된다.

더 간단하게

  • template_name
    ListView에서 template_name의 기본값은 [model_name]_list.html이다.
    DetailView에서 template_name의 기본값은 [model_name]_detail.html이다.
    CreateView에서 template_name의 기본값은 [model_name]_form.html이다.
    UpdateView에서 template_name의 기본값은 [model_name]_form.html이다.
    DeleteView에서 template_name의 기본값은 [model_name]_confirm_delete.html이다.
    템플릿의 이름을 기본값과 일치하게 작성했다면 생략해도 된다.

  • page_kwarg
    page_kwarg의 기본값은 page이다.
    템플릿에서 page를 키워드로 사용하고 있다면 생략해도 된다.

  • pk_url_kwarg
    pk_url_kwarg의 기본값은 pk이다.
    views.py에서 url패턴에 있는 데이터 조회를 위한 키워드(<\int:pk>)를 pk로 사용한다면 생략해도 된다.

Tags:

Categories:

Updated:

Leave a comment