클래스형 뷰가 개발자들이 자주 쓰는 기능들을상위 클래스로상속받아 사용한다면, 제네릭 뷰는상속받을 수 있는이미 만들어진 상위 클래스를 말한다.
CRUD에서Read에 해당하는 클래스형 함수를 만들 때, 모델에 접근해 데이터를 불러오는 코드를 직접 작성하지 않고도ListView또는DetailView제네릭 뷰를 상속받으면 접근할모델과 렌더할템플릿만 작성하면 된다.
이전 포스팅에 작성된
클래스형 함수PostCreateView는 장고의View를 상속받아 작성됐다.제네릭 뷰를 상속받아 더 간편하게CRUD의CREATE기능을 구현하는 방법을 알아본다.
기존에 작성된 코드와
제네릭뷰(CreateView)를 상속받아 작성된 코드를 비교해보자.
기존에 작성된 코드는 아래와 같다.
# class PostCreateView(View):
# def get(self, request):
# post_form = PostForm()
# context = {"post_form": post_form}
# return render(request, 'posts/post_form.html', context=context)
# 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)
# else:
# context = {"post_form": post_form}
# return render(request, 'posts/post_form.html', context=context)
제네릭 뷰(CreateView)를 상속받아 다시 작성된 코드는 아래와 같다.
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})
아래의 코드는 접근할
모델, 사용할폼, 렌더할템플릿, 그리고 게시글 생성 후 이동할url만 작성했지만 기능은 일치한다.
그 이유는 상속받은
CreateView제네릭 뷰에서 다른 내용들을 포함하고 있기 때문이다.
CreateView는 사용할폼을 템플릿에 전달할 때context에{"form": {사용할 폼}}을 전달한다. 따라서 기존에context로 전달하는폼의키가 다른 이름이라면템플릿에서 변경해야 한다.
<dear>프로젝트에서는 기존에는{"post_form":PostForm}으로 전달 했는데키가post_form에서form으로 변경되어 전달되기 때문에템플릿에서 해당 부분만 변경하면 된다.
reverse함수는redirect과는 다르게 url을 문자열로 생성하고 반환하는 역할만 한다.CreateView제네릭 뷰에서 이미 해당 url로 이동하는 기능을 내장하고 있기 때문에reverse를 사용하는 것 같다.정확한 이해를 위해 각종 블로그를 찾아봤는데
redirect는 url 경로가 변경되면 변경된 경로를 모두 찾아 수정해야하고reverse는name속성을 이용해 경로를 수정하지 않아도 된다는 내용이 많았다.그러나
redirect도 마찬가지로name속성을 이용하면 url 경로를 하드코딩하지 않아도 되기 때문에 변경된 경로를 모두 찾아 수정할 필요가 없지 않나 라는 의문이 들었다.해당 의문에 대한 명확한 답을 찾게된다면 다시 정리해서 수정하겠다.
url 패턴에서
post_create를PostCreateView로 변경해야 한다.
urls.py
urlpatterns = [
# path('', views.index),
path('', views.PostListView.as_view(), name="post-list"),
path('posts/new/', views.PostCreateView.as_view(), name="post-create"),
path('posts/<int:post_id>/', views.PostDetailView.as_view(), name="post-detail"),
path('posts/<int:post_id>/edit/', views.post_update, name="post-update"),
path('posts/<int:post_id>/delete/', views.post_delete, name="post-delete"),
]