[REAL Python – Django] – “Django – comment create/update/delete 구현”

[REAL Python – Django] – “Django – comment create/update/delete 구현”

4월 4, 2022

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 오류를 발생시킵니다.

생성, 수정, 삭제가 구현된 것을 볼 수 있습니다.

Leave A Comment

Avada Programmer

Hello! We are a group of skilled developers and programmers.

Hello! We are a group of skilled developers and programmers.

We have experience in working with different platforms, systems, and devices to create products that are compatible and accessible.