본문 바로가기

77 Django CBV 댓글기능-Ajax 수정/삭제

77.1 수정 삭제 url 등록 - urls.py

댓글등록을 완료하고 pythonblog.co.kr에 적용도 하였습니다.
현재는 등록만 가능하니 이번에는 수정/삭제를 기능을 추가합니다.

기능을 구현할 url 패턴을 urls.py에 등록합니다.

#myapp/common/common_urls.py

urlpatterns = [   
       ...  
       ...
    path('comment/<int:comment_id>/edit',views.EditComment.as_view(), name='edit_comment'),
    path('comment/<int:comment_id>/del', views.DelComment.as_view(), name='del_comment'),
    path('comment/<int:comment_id>/<int:app_id>/mod', views.ModComment.as_view(), name='mod_comment'),
]
  • edit_comment : 수정 버튼을 클릭시 수정폼을 리턴합니다.
  • del_comment: 삭제 시 pycomment 모델의 use_yn 필드를 N 으로 업데이트 합니다.
  • mod_comment : 수정한 내용을 db에 반영합니다.
  • comment_id 는 pycomment 모델의 pk입니다.
  • app_id는 화면 상세 페이지의 pk 입니다.

77.2 수정 삭제 기능 구현 - view.py

view 에서 수정, 삭제 기능 클래스(EditComment, DelComment, ModComment 를 만듭니다.

from django.http import JsonResponse
from .common_forms import CommentForm
from .common_models import PyComment

                 ...
                 ...
                 ...
                 ...


class EditComment(generic.FormView):
    form_class = CommentForm
    model = PyComment

    def get_object(self):   
        return PyComment.objects.get(id=self.kwargs.get('comment_id'), use_yn = 'Y')

    def get_initial(self):      
        PyComment = self.get_object()
        return {'app_id':PyComment.app_id, 'app_name':PyComment.app_name, 'host':PyComment.host, 'host_id':PyComment.host_id,
                'comment_body':PyComment.comment_body, 'comment_img_url':PyComment.comment_img_url, 'regist_usnm':PyComment.regist_usnm
                }

    def get(self, request, *args, **kwargs):
        return JsonResponse({'form':self.get_form().as_p()})

class ModComment(generic.FormView):
    form_class = CommentForm

    def post(self, request, *args, **kwargs):
        form = self.get_form()      

        if form.is_valid():
            comment_body = self.unScript(form.cleaned_data['comment_body'])
            print("comment_body : ",comment_body)
            n_comment = form.save(commit=False)
            n_comment.id = self.kwargs.get('comment_id')
            n_comment.comment_body = comment_body
            comment = n_comment.save(update_fields=['comment_body'])   #=None: all , =[]:no update, =[filed]:update필드지정                 
            return JsonResponse( {'isSuccess':'Y','error_msg':'','id':n_comment.id,'comment_body':comment_body})
        else:   

            error_msg = ''          
            for key in form.errors.as_data():
                error_msg = f'{self.getKor(key)} {form.errors[key][0]}'
                break

        return JsonResponse({'isSuccess':'N','error_msg':error_msg})

    def unScript(self, text):
        return text.replace('<','&lt;').replace('>','&gt;') 

class DelComment(generic.View):
    def post(self, request, *args, **kwargs):
        comment_queryset = PyComment.objects.filter(id=self.kwargs.get('comment_id'), use_yn = 'Y')

        if comment_queryset.count() == 1:           
            cmt = comment_queryset.update(use_yn='N')           
            return JsonResponse({'isSuccess':'Y','error_msg':'','id':self.kwargs.get('comment_id')})

        return JsonResponse({'isSuccess':'N','error_msg':'delete fail'})
  • class EditComment : 화면에서 수정 버튼을 클릭시 동작하는 클래스 입니다.
    1) comment_id로 py_comment모델에 등록된 데이터를 가져와 form에 셋팅합니다.
    2) 셋팅된 form을 화면으로 리턴합니다.

  • class ModComment: 화면에서 수정사항을 적용하면 동작합니다.
    1) form.is_valid()에서 수정된 값(comment_body)의 밸리데이션을 체크합니다.
    2) save() 함수로 업데이트 합니다. update_fields 로 변경할 필드를 지정합니다.
    3) 성공/ 실패 결과를 리턴합니다.

  • class DelComment : 화면에서 삭제 버튼 클릭시 동작합니다.
    1) objects.filter로 쿼리셋 결과를 받습니다.
    2) count()로 데이터가 있는지 확인 후 있으면 댓글 여부(use_yn)을 사용안함(N)으로 업데이트 합니다.
    3) 성공/ 실패 결과를 리턴합니다.

77.3 화면 기능 구현 - html script

HTML태그 생성시 고유한 comment_box{{comment_id}}를 부여하여 해당 태그를 수정하거나 삭제 할 수 있도록 구현

<div class="row">
                ...     
                ...
                ...
                <div id="singleComment">
                    {% for comment in comments %}
                    <div id="comment_box_{{comment.id}}" class="d-flex mb-4">
                        <div class=" flex-sm-shrink-0">
                            <img class="rounded-circle" src="{{comment.comment_img_url|imagePathComment}}" alt="{{comment.host}}"  />
                        </div>

                        <div class="ms-3">
                            <div class="fw-bold">
                                <span class="text-gray-900 font-weight-bolder text-lg">{{ comment.regist_usnm }}</span> <span class="text-xs"> {{comment.regist_dt | date:'Y.m.d H:i:s' }}</span>
                                <span class="edit btn text-info btn-ssm" data-body-idx="{{comment.id}}" data-action-edit="{% url "common:edit_comment" comment.id %}" data-action-mod = "{% url "common:mod_comment" comment.id pageInfo.id  %}">update</span>                            
                                <span class="del btn text-info btn-ssm" data-action-del="{% url "common:del_comment" comment.id %}" >delete</span>
                            </div>
                            <span id="comment_body_{{comment.id}}">
                            {{ comment.comment_body | linebreaks }}
                            </span>
                        </div>
                     {% endfor %}
                      ...
                      ...
  • comment_box_{{comment.id}} : 한개의 댓글영역에 comment.id 부여
  • <span class="edit ... : 수정폼 함수 호출 이름
  • <span class="del ... : 삭제 함수 호출 이름
  • data-xxxx : 데이터 속성을 사용하여 필요한 값을 저장 data-body-idx, data-action-edit, data-action-mod 등
  • comment_body_ ... : 댓글 수정폼 넣을곳
 $(document).on("click", ".edit", function() {            
        var comment_body_idx = $(this).attr('data-body-idx'); //comment 위치        
        action_url =$(this).attr('data-action-mod');
        noticefyAlert("info","request waiting for editor");

        $.ajax({             
            url:  $(this).attr('data-action-edit'),         
            type: "GET",             
            beforeSend : function(xhr){xhr.setRequestHeader('csrfmiddlewaretoken','{{ csrf_token }}');},
            success: function(data){                
                tForm = '';
                tForm +='<form id="commentFormMod" class="form-inline" method="POST" action="'+action_url+'">';
                tForm += data.form
                tForm +='   <div class="form-group row">';
                tForm +='       <button class="mod btn btn-primary ml-4" type="button" >수정</button>';
                tForm +='   </div>';
                tForm +='</form>';

                $('#comment_body_'+comment_body_idx).empty();                                
                $('#comment_body_'+comment_body_idx).append(tForm);                
            },
            error: function(request, status, error){
                console.log(error)
                return;  
            },            
        });
    });
  • update 버튼 클릭시 수정폼 생성
$(document).on("click", ".mod", function() {
        $.ajax({
            url: $('#commentFormMod').attr('action'),
            method:"POST",
            beforeSend : function(xhr){xhr.setRequestHeader('X-CSRFToken','{{ csrf_token }}');},
            data:$('#commentFormMod').serialize()
        }).done(function(data) {            
            noticefyAlert("success","success");
            $('#comment_body_'+data.id).empty(); 
            $('#comment_body_'+data.id).append(data.comment_body);
        });
        return;
    });
  • 수정완료 버튼 클릭시 db저장 후 변경내용 화면에 표시
$(document).on("click", ".del", function() {
        $.ajax({
            url:$(this).attr('data-action-del'),
            method:"POST",
            beforeSend : function(xhr){xhr.setRequestHeader('X-CSRFToken','{{ csrf_token }}');},
            data:$('#commentFormMod').serialize()
        }).done(function(data) {   
            console.log(data.isSuccess) 
            if(data.isSuccess == 'Y'){
                $('#comment_box_'+data.id).remove();
                noticefyAlert("success","success");
            }else{
                noticefyAlert("danger",data.error_msg);
            }     
        });
        return;
    });
  • 삭제 버튼 클릭시 db 수정(use_yn) 후 삭제된 댓글 remove()

77.4 화면 기능 구현 - html script

서버 반영 후에 수정/ 삭제를 확인해 봅니다.

현재 인증이 없어 아무나 작성할 글을 수정, 삭제 할 수 있네요.

현재글 : 77 Django CBV 댓글기능-Ajax 수정/삭제
Comments
Login:

a**sk3939@naver.com naver
a**sk3939@naver.com 2022.12.12 14:50:28

잘보고 갑니다

Copyright © PythonBlog 2021 - 2022 All rights reserved
Mail : PYTHONBLOG