장고 - Ajax 이용한 댓글 기능 구현

댓글 생성하기

1. 상세 글 조회 페이지에 댓글 목록 추가

  • 원하는 위치에 댓글 목록 부분을 작성한다.
  • 경로 : board > templates > board > document_detail.html
    1
    2
    3
    <div id="docs_comment_list_area">
    {% include 'board/comment_list.html' %}
    </div>

2. 댓글 목록 부분 HTML 코드 작성

  • 댓글 목록을 어떻게 구성할 것인지 정의한다.
  • 경로 : board > templates > board

    • comment_list.html

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <table class="table table-striped" id="comment_list">
      <thead>
      <tr>
      <th colspan="7" class="align-left">댓글 목록</th>
      </tr>
      </thead>
      <tbody>
      {% for comment in comments %}
      {% include 'board/comment/comment_single.html' %}
      {% endfor %}
      </tbody>
      </table>
    • comment > comment_single.html

      1
      2
      3
      4
      5
      6
      7
      <tr class="comment_row">
      <td colspan="3" class="comment_text">{{comment.text}}</td>
      <td>{{comment.author.username}}</td>
      <td>{{comment.created}}</td>-
      <td><a href="{% url 'board:comment_update' comment.id %}" class="btn btn-warning btn-sm btn_comment_update">update</a></td>
      <td><a href="{% url 'board:comment_delete' comment.id %}" class="btn btn-danger btn-sm btn_comment_delete">delete</a></td>
      </tr>

3. Ajax 요청 기능 구현

  • Ajax를 이용하여 댓글 수정을 요청하는 부분을 작성한다.
  • 경로 : board > templates > board > document_detail.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <script type="text/javascript">
    $(function() {
    $('#comment_form').submit(function(e) {
    // alert('댓글쓰기 완료');
    // 댓글 남기기
    $('input[name="is_ajax"]').val("1");
    url = $(this).attr('action');
    params = $(this).serialize();
    $.ajax({
    url:url,
    method:"POST",
    data:params
    }).done(function(data) {
    // 댓글 입력창 내용 비우기
    $('#id_text').val("");
    $('#comment_list tbody').prepend(data.html); // tbody 시작 지점에 요소 끼워넣기
    // is_ajax 값 초기화
    $('input[name="is_ajax"]').val("");
    });
    return false;
    });
    });

4. Ajax 요청에 따른 작업 진행 내용 명시

  • Ajax 요청을 받아 데이터베이스에서 수행할 작업을 명시한다.
  • 경로 : board > views.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    from django.template.loader import render_to_string
    def comment_create(request, document_id):
    # is_ajax : ajax 기능에 의해 호출된 것인지 구분하기 위한 값
    is_ajax = request.POST.get('is_ajax')

    document = get_object_or_404(Document, pk=document_id)
    comment_form = CommentForm(request.POST)
    comment_form.instance.author_id = request.user.id
    comment_form.instance.document_id = document_id
    if comment_form.is_valid():
    comment = comment_form.save()

    # 만약 ajax에 의해 호출되었다면 redirection 없이 Json 형태로 응답
    if is_ajax:
    # 데이터 만들어서 던져주기
    html = render_to_string('board/comment/comment_single.html',{'comment':comment})
    return JsonResponse({'html':html})
    return redirect(reverse('board:detail', args=[document_id]))

댓글 수정하기

1. 댓글에 ‘update’ 버튼 추가

  • update 버튼을 클릭하면 수정 페이지로 이동하는 코드를 작성한다.
  • 경로 : board > templates > board
    • comment > comment_single.html
      1
      2
      3
      4
      5
      6
      7
      <tr class="comment_row">
      <td colspan="3" class="comment_text">{{comment.text}}</td>
      <td>{{comment.author.username}}</td>
      <td>{{comment.created}}</td>-
      <td><a href="{% url 'board:comment_update' comment.id %}" class="btn btn-warning btn-sm btn_comment_update">update</a></td>
      <td><a href="{% url 'board:comment_delete' comment.id %}" class="btn btn-danger btn-sm btn_comment_delete">delete</a></td>
      </tr>

2. 수정 페이지 코드 작성

  • ‘update’ 버튼을 클릭했을 때, 조회되는 페이지 코드를 작성한다.
  • 경로 : board > templates > board > comment > comment_update.html
    1
    2
    3
    4
    5
    6
    7
    8
    {% extends 'base.html' %}
    {% block content %}
    <form action="" method="post">
    {% csrf_token %}
    {{form.as_p}}
    <input type="submit" value="Update" class="btn btn-outline-warning">
    </form>
    {% endblock %}

3. Ajax 요청 기능 구현

  • Ajax를 이용하여 댓글 수정을 요청하는 부분을 작성한다.
  • 경로 : board > templates > board > document_detail.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    $('.btn_comment_update').click(function(e) {
    e.preventDefault();
    url = $(this).attr('href')+'?is_ajax=1';
    comment = $(this).parent().siblings('.comment_text'); // 원래 댓글을 찾음
    input = "<input type='text' class='update_text' value='"+comment.text()+"'>";
    comment.html(input);
    $('.update_text').keypress(function(e){
    if (e.keyCode==13) {
    text = $(this).val();
    $.ajax({
    url:url,
    data:{
    text:text
    }
    }).done(function(data) {
    if(data.works) {
    comment.text(text);
    }
    });
    }
    });
    return false;
    text = prompt('수정될 댓글 내용을 입력하세요.', comment.text()); // 원래 댓글을 프롬프트로 보여줌
    if (text==null) return false; // 입력 취소면 함수 종료
    $.ajax({
    url:url,
    data:{
    text:text
    }
    }).done(function(data) {
    if(data.works) {
    comment.text(text);
    }
    });
    });

4. Ajax 요청에 따른 작업 진행 내용 명시

  • Ajax 요청을 받아 데이터베이스에서 수행할 작업을 명시한다.
  • 경로 : board > views.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    def comment_update(request, comment_id):
    is_ajax, data = (request.GET.get('is_ajax'), request.GET) if 'is_ajax' in request.GET else (request.POST.get('is_ajax', False), request.POST)

    comment = get_object_or_404(Comment, pk=comment_id)
    document = get_object_or_404(Document, pk=comment.document.id)
    if request.user != comment.author:
    messages.warning(request, "권한 없음")
    return redirect(document)

    if is_ajax:
    form = CommentForm(data, instance=comment)
    if form.is_valid():
    form.save()
    return JsonResponse({'works':True})

    if request.method == "POST":
    form = CommentForm(request.POST, request.FILES, instance=comment)
    if form.is_valid():
    form.save()
    return redirect(document)
    else:
    form = CommentForm(instance=comment)
    return render(request, 'board/comment/comment_update.html', {'form':form})

댓글 삭제하기

1. 댓글에 ‘delete’ 버튼 추가

  • update 버튼을 클릭하면 삭제 페이지로 이동하는 코드를 작성한다.
  • 경로 : board > templates > board

2. 삭제 페이지 코드 작성

  • ‘update’ 버튼을 클릭했을 때, 조회되는 페이지 코드를 작성한다.
  • 경로 : board > templates > board > comment > comment_delete.html
    1
    2
    3
    4
    {% extends 'base.html' %}
    {% block content %}
    // 'delete' 버튼 클릭 시, 이동하는 화면에 대한 코드 작성
    {% endblock %}

3. Ajax 요청 기능 구현

  • Ajax를 이용하여 댓글 삭제를 요청하는 부분을 작성한다.
  • 경로 : board > templates > board > document_delete.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    $('.btn_comment_delete').click(function(e) {
    e.preventDefault();
    var input = confirm('댓글을 삭제하시겠습니까?');
    if (input==true) {
    alert('댓글을 삭제하였습니다.');
    comment = $(this).parents('tr'); // 버튼을 감싸고 있는 tr 찾기
    url = $(this).attr('href')+"?is_ajax=1"; // ajax 호출임을 구분할 수 있게 값 추가
    $.ajax({
    url:url
    }).done(function(data) {
    if (data.works) {
    comment.remove(); // 해당 객체 지우기
    }
    });
    }
    });

4. Ajax 요청에 따른 작업 진행 내용 명시

  • Ajax 요청을 받아 데이터베이스에서 수행할 작업을 명시한다.
  • 경로 : board > views.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def comment_delete(request, comment_id):
    is_ajax = request.GET.get('is_ajax') if 'is_ajax' in request.GET else request.POST.get('is_ajax',False)
    comment = get_object_or_404(Comment, pk=comment_id)
    document = get_object_or_404(Document, pk=comment.document.id)

    if request.user != comment.author and not request.user.is_staff and request.user != document.author:
    messages.warning(request, "권한 없음")
    return redirect(document)

    if is_ajax:
    comment.delete()
    return JsonResponse({"works":True})

    if request.method == "POST":
    comment.delete()
    return redirect(document)
    else:
    return render(request, 'board/comment/comment_delete.html', {'object': comment})