[REAL Python – Django] – “Django – comment create/update/delete 구현”
[REAL Python – Django] – “Django – comment create/update/delete 구현”
Create – forms.py
사용하기
이전에 모델을 만들어놓았으므로 폼을 구현해 볼 것입니다.
from .models import Comment
from django import forms
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('content',)
해야 할 것은 단순히 앱 폴더 아래에 forms.py
파일을 만든 다음 메타 클래스에 어떤 모델을 사용할 것인지, 모델의 어떤 필드를 사용할 것인지를 정해주는 것뿐입니다.
Create – views.py
수정하기
context['comment_form'] = CommentForm
해당 뷰를 처리하는(현재 작업의 경우 포스트 상세 페이지)클래스의 get_context_data
함수에 위의 코드를 추가합니다. 그렇게 함으로서 폼을 뷰에 넘겨줄 수 있습니다.
컨텍스트를 넘겨주었으므로 템플릿에서 {{ comment_form | crispy }}
를 입력해 봅시다. 그 부분이 아래와 같이 폼이 만들어지는 것을 확인할 수 있습니다.
Create – form action
알아보고 url, view
처리하기
{% if user.is_authenticated %}
<form class="mb-4" id="comment-form" method="POST"
action="{{ post.get_absolute_url }}new_comment/">
<div class="form-group">
{{ comment_form | crispy }}
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
<hr/>
{% else %}
<a role="button" class="btn btn-outline-dark btn-sm" href="#" data-toggle="modal"
data-target="#loginModal">
Log in and leave a comment
</a>
{% endif %}
위의 템플릿 코드에서 action="{{ post.get_absolute_url }}new_comment/"
의 부분을 살펴보겠습니다. HTML
에서 form
태그의 action
속성은 폼으로 데이터를 보낼 때에 데이터를 받을 곳을 알려주는 url
을 알려주는 역할을 합니다. 위의 코드에 따라서 댓글을 작성하고 제출을 한다면 포스트 주소/new_comment/
라는 곳으로 데이터가 전송될 겁니다. 이 부분을 처리하려면 첫 번째로 urls.py
부분을 고쳐야겠죠.
path('<int:pk>/new_comment/', views.new_comment),
위의 코드를 url 패턴에 추가해 줍니다. 해당 url
으로 접근하면 뷰의 new_comment
에서 처리하도록 했죠. 이제는 뷰를 고칠 시간입니다.
def new_comment(request, pk):
if request.user.is_authenticated: # 로그인하지 않은 경우에는 접근하지 못하도록
post = get_object_or_404(Post, pk=pk) # pk가 없는 경우에는 404 에러 발생
if request.method == 'POST': # 폼에서 요청해온 방식이라면
comment_form = CommentForm(request.POST) # POST 정보로 얻어온 정보를 담음
if comment_form.is_valid(): # 폼이 유요하다면 DB에 저장
comment = comment_form.save(commit=False) # 바로 DB에 저장하지 않음
comment.post = post # 댓글의 외래키로 연결된 포스트는 pk로 가져온 포스트가 됨
comment.author = request.user # 로그인한 사람의 정보로 저자 정보 채우기
comment.save()
return redirect(comment.get_absolute_url())
else:
return redirect(post.get_absolute_url()) # 브라우저에 입력해서 들어오면 포스트 페이지로 리다이렉트
else:
raise PermissionDenied
코드를 작성하면서 느낀 것은 DB를 가지고 노는 것이 굉장히 간단하다는 것이었습니다. 이렇게 댓글 작성까지 완료.
Update – urls.py -> views.py
수정
path('update_comment/<int:pk>/', views.CommentUpdate.as_view()),
urls.py
에 위의 코드 추가
class CommentUpdate(LoginRequiredMixin, UpdateView):
model = Comment
form_class = CommentForm
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated and request.user == self.get_object().author: # 유저가 로그인되어있고 작성자와 같은지 확인
return super(CommentUpdate, self).dispatch(request, *args, **kwargs)
else:
raise PermissionDenied # 같지 않다면 오류 발생
이번 뷰는 클래스로 처리했습니다.
템플릿 작성 중 오류
{% if comment.created_at != comment.modified_at %}
<p class="text-muted float-right">
{# <small>Creaated : {{ comment.created_at }}</small><br/> #}
<small>Modified : {{ comment.modified_at }}</small>
</p>
{% endif %}
의도는 생성일자와 수정일자가 다른 경우 수정일자가 아래에 표시되도록 하려고 했는데..
문제는 년-월-일-시-분 까지는 괜찮은데 뒷부분의 초가 다르게 저장된다는 것이 문제였습니다. 일단 주석 처리 해 놓고 다음을 기약하기로..
Delete – urls.py, views.py
수정하기
path('delete_comment/<int:pk>/', views.delete_comment),
url
패턴에 다음의 경로를 추가시켜 줍니다. 모델 만들기-> 템플릿 작성-> urls.py
-> views.py
순서의 과정은 비슷하네요.
def delete_comment(request,pk): # 삭제 요청과 pk값을 인자로 받는다.
comment = get_object_or_404(Comment, pk=pk) # pk로 댓글을 가져오거나 HTTP404를 발생시킨다.
post = comment.post # 삭제하려는 댓글의 post
if request.user.is_authenticated and request.user == comment.author:
comment.delete()
return redirect(post.get_absolute_url())
else:
raise PermissionDenied
https://docs.djangoproject.com/ko/4.0/intro/tutorial03/#a-shortcut-get-object-or-404
Django의 get_objcet_or_404
는 직관적인 이름처럼 object
를 받아오거나 그것이 없으면 HTTP 404 오류를 발생시킵니다.
생성, 수정, 삭제가 구현된 것을 볼 수 있습니다.