[REAL Python – Django] – “Django – 폼을 통한 Create 구현하기”
[REAL Python – Django] – “Django – 폼을 통한 Create 구현하기”
Django에서 제공하는 CreateView
클래스
A view that displays a form for creating an object, redisplaying the form with validation errors (if there are any) and saving the object.
개체를 생성하기 위한 양식을 표시하고 유효성 검사 오류가 있는 양식을 다시 표시하고(있는 경우) 개체를 저장하는 보기입니다.
https://docs.djangoproject.com/en/4.0/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView
views.py
코드 작성하기
클래스 기반으로 뷰를 구성할 겁니다.
class PostCreate(CreateView):
model = Post
fields = ['title','hook_text', 'content', 'head_image', 'file_upload', 'category']
urls.py
코드 작성하기
path('create_post/', views.PostCreate.as_view()),
일련의 비슷한 과정입니다. /create_post/
인 경우 views.py
의 PostCreate
클래스에서 처리하라고 알려주고 있습니다.
위의 PostCreate
클래스에서 model = Post
라고 정해주었고, PostCreate
클래스는 CreateView
클래스를 상속받아 만들어진 것이기 때문에 접미사로 _form
이 붙은 템플릿이 필요합니다.(기본값)
이에 관련해서는 Django의 공식 문서에서 언급을 찾을 수 있었습니다.
The CreateView page displayed to a GET request uses a template_name_suffix of ‘_form’. For example, changing this attribute to ‘_create_form’ for a view creating objects for the example Author model would cause the default template_name to be ‘myapp/author_create_form.html’.
https://docs.djangoproject.com/en/4.0/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView.template_name_suffix
templates
작성하기
<table>
{{ form }}
</table>
신기했던 것은{{ form }}
부분이었습니다. 위는 템플릿 코드 중 일부이고,
<table>
<tr>
<th><label for="id_title">Title:</label></th>
<td>
<input type="text" name="title" maxlength="30" required id="id_title">
</td>
</tr>
<tr>
<th><label for="id_hook_text">Hook text:</label></th>
<td>
<input type="text" name="hook_text" maxlength="100" id="id_hook_text">
</td>
</tr>
<tr>
<th><label for="id_content">Content:</label></th>
<td>
<textarea name="content" cols="40" rows="10" required id="id_content">
</textarea>
</td>
</tr>
<tr>
<th><label for="id_head_image">Head image:</label></th>
<td>
<input type="file" name="head_image" accept="image/*" id="id_head_image">
</td>
</tr>
<tr>
<th><label for="id_file_upload">File upload:</label></th>
<td>
<input type="file" name="file_upload" id="id_file_upload">
</td>
</tr>
<tr>
<th><label for="id_category">Category:</label></th>
<td>
<select name="category" id="id_category">
<option value="" selected>---------</option>
<option value="1">파이썬</option>
<option value="2">자바스크립트</option>
<option value="3">자바</option>
</select>
</td>
</tr>
</table>
위는 실제로 생성된 페이지의 HTML 코드입니다. 위의 세 줄이 아래의 HTML 코드로 나타났네요. 이는 구현했던 PostCreate
에서 폼을 구성해 주기 때문입니다.
LoginRequiredMixin
을 이용해서 로그인한 사용자만 글을 작성할 수 있도록 하기
LoginRequiredMixin
에 대한 설명은 아래에 나와 있습니다.
https://docs.djangoproject.com/en/4.0/topics/auth/default/#the-loginrequired-mixin – 장고 공식 문서
class PostCreate(LoginRequiredMixin, CreateView):
클래스를 상속받으면 되는데, 클래스 기반 뷰에서만 사용 가능하며, LoginRequiredMixin
은 꼭 가장 왼쪽에 코드가 위치해야 합니다.
로그인하지 않고 게시글을 생성하기 위한 URL
에 접근하면 위와 같이 로그인 페이지로 리디렉션됩니다.
글 작성 시 자동으로 로그인한 사용자가 저자로 표시되도록 하기
def form_valid(self, form):
current_user = self.request.user
if current_user.is_authenticated:
form.instance.author = current_user
return super(PostCreate, self).form_valid(form)
else:
return redirect('/blog/')
장고의 CreateView
클래스에는 기본적으로 form_valid
라는 메서드를 내장하고 있습니다. 그것에 대한 설명은 아래와 같이 나와 있습니다.
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
form_valid
라는 메서드는 폼 데이터가 보내지면 호출되고, HttpResponse
를 반환해야 한다고 합니다.
그러면 위에서 재정의한 form_valid
메서드를 보면, 현재 웹 사이트에 방문한 유저가 로그인되어 있다면 (if current_user.is_authenticated:)
폼의 author
필드에는 current_user
를 담도록 되어 있습니다. 아니라면(else:
), '/blog/'
로 리디렉트 되도록 코드를 작성했습니다.
UserPassesTestMixin을 이용해서staff
만 글 작성 허용하기
class PostCreate(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = Post
fields = ['title','hook_text', 'content', 'head_image', 'file_upload', 'category']
# author : 로그인했다면 입력할 필요 없음, created_at : 작성 시에 자동으로 시간이 채워짐, tags : 방문자가 텍스트로 입력하게끔 구현할 것
def test_func(self):
return self.request.user.is_superuser or self.request.user.is_staff
def form_valid(self, form):
current_user = self.request.user
if current_user.is_authenticated and (current_user.is_staff or current_user.is_superuser):
form.instance.author = current_user
return super(PostCreate, self).form_valid(form)
else:
return redirect('/blog/')
다른 프레임워크에 비해서(써 본 건 고작 코드이그나이터 정도지만..) 장고는 굉장히 쉽게 이런저런 기능을 넣을 수 있게 설계되어 있다는 것이 참 편리한 것 같습니다.