Ajax - ajax 이용한 실시간 댓글 생성 및 좋아요 개수 표시

  • 이번 포스트에서는 ajax를 이용하여 댓글 작성 및 특정 댓글의 좋아요 개수를 표시하는 방법에 대해 알아볼 것이다.

ajax를 이용한 실시간 댓글 작성 및 좋아요 개수 표시

1. 서버에 ajax 요청

  • 경로 : post > templates > post > post_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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    {% block content %}
    ...
    <form action="{% url 'post:comment_create' object.id %}" method="post" id="comment_form">
    {% csrf_token %}
    <input type="hidden" name="is_ajax" value="">
    <div class="row" style="width:590px; padding-right:10px;">
    <div id="comment_write" class="col-8" style="padding:0 0 0 5px;">{{comment_form.text}}</div>
    <div class="col">
    <input type="submit" value="댓글 입력" class="btn btn-outline-primary form-control">
    </div>
    </div>
    </form>
    <!-- 유저들 댓글 조회 부분 -->
    <div id="comment_list">
    {% include 'post/comment_list.html' %}
    </div>
    ...
    {% endblock %}

    {% block extra_script %}
    <!-- 댓글 폼 작성 시 -->
    $("#comment_form").submit(function(e){
    e.preventDefault();
    <!-- name이 is_ajax인 input type의 value를 1로 설정 -->
    $('input[name="is_ajax"]').val("1");
    <!-- 해당 input의 action 태그에 있는 경로를 url로 저장 -->
    url = $(this).attr('action');
    <!-- 해당 input에 저장된 데이터를 하나로 모아(serialize) params 변수에 저장 -->
    params = $(this).serialize();
    $.ajax({
    url: url,
    method: "POST",
    data: params,
    }).done(function(data){
    <!-- 댓글 조회 부분에 data.html 추가 -->
    $('#comment_list').prepend(data.html);
    <!-- input 태그의 name이 is_ajax인 value값 초기화 -->
    $('input[name="is_ajax"]').val("");
    <!-- 댓글 입력부분의 문자열 초기화 -->
    $('#id_text').val("");
    });
    });
    <!-- 댓글 좋아요 버튼 클릭시 -->
    $(".btn-comment-like").click(function(e){
    e.preventDefault();
    <!-- 댓글 좋아요 버튼 클릭한 객체를 selected_object 변수에 할당 -->
    selected_object = $(e.currentTarget);
    <!-- selected_object의 href 태그에 있는 경로를 url 변수로 저장 -->
    url = selected_object.attr('href')
    console.log(url);
    $.ajax({
    url:url,
    method:"POST",
    data:{
    'csrfmiddlewaretoken':'{{csrf_token}}',
    'is_ajax':true,
    },
    }).done(function(data){
    if(data.works){
    <!-- 서버에서 수신한 data key값으로 works가 있는 경우 -->
    <!-- selected_object의 html부분의 whitespace 제거한 데이터를 str_comment_like 변수로 저장 -->
    str_comment_like = selected_object.html().trim();
    <!-- str_comment_like에서 숫자를 match한 결과가 null값이면 selected_object에 html 형식으로 '좋아요 1개' 표시 -->
    if(str_comment_like.match(/[0-9]+/g)==null){
    selected_object.html("&emsp;좋아요 1개")
    }
    <!-- str_comment_like에서 숫자를 match한 결과가 null이 아닌 경우 -->
    else{
    <!-- str_comment_like에서 숫자로만 되어 있는 문자열을 int_comment_like 변수에 저장 및 int type으로 변경 후, 개수 1 증대한 값을 comment_like 변수에 저장 -->
    int_comment_like = str_comment_like.match(/[0-9]+/g);
    comment_like = parseInt(int_comment_like[0]) + 1;
    <!-- selected_object.html에 좋아요 개수 표시 -->
    selected_object.html("&emsp;좋아요 "+comment_like+"개")
    }
    }
    });
    });
  • 경로 : post > templates > post > comment_list.html

    1
    2
    3
    {% for comment in comments %}
    {% include 'post/comment_single.html' %}
    {% endfor %}
  • 경로 : post > templates > post > comment_single.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <div style="margin-bottom: 20px;">
    <div class="img-profile" style="background-image:url({{comment.author.profile.url}})"></div>
    <div style="float:left; height:100%; width:550px; line-height:100%;">
    <div style="display:inline-block; vertical-align:middle; line-height:normal;">
    <p style="padding:10px; border-radius:25px; background-color:rgb(237,237,237); display:inline-block; margin:0">
    <a style="color:rgb(37,71,194); font-weight:bold;" href="#">{{comment.author.last_name}}{{comment.author.first_name}}</a>&emsp;{{comment.text}}
    </p>
    <a class="btn-comment-like" href="{% url 'post:comment_like' comment.id %}">&emsp;좋아요 {% if comment.like %}{{comment.like}}개{% endif %}</a>
    <a class="btn-comment-update-delete" href="{% url 'post:comment_update' comment.id %}">&emsp;수정</a>
    <a class="btn-comment-update-delete" href="{% url 'post:comment_delete' comment.id %}">삭제</a>
    </div>
    </div>
    <div style="clear:both;"></div>
    </div>

2. 서버에서 ajax로 데이터 송신

  • 경로 : post > 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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    def comment_create(request, post_id):
    # ajax 요청에서 is_ajax 데이터 수신
    is_ajax = request.POST.get('is_ajax')
    # 특정 post_id를 pk 값으로 갖는 post 객체를 post 변수로 저장
    post = Post.objects.get(pk=post_id)
    # 댓글폼에 입력한 데이터를 POST 형식으로 요청한 댓글폼을 comment_form 변수로 저장
    comment_form = CommentForm(request.POST)
    # 요청한 유저를 comment_form의 작성자로 저장
    comment_form.instance.author_id = request.user.id
    comment_form.instance.post_id = post_id
    # comment_form이 검증 완료되었다면, comment_form 데이터 저장
    if comment_form.is_valid():
    comment = comment_form.save()
    # ajax 요청 데이터에 is_ajax 가 있다면,
    if is_ajax:
    # comment_single.html에 있는 문자열을 렌더링 및 comment를 context data로 설정하여 html 변수에 저장
    html = render_to_string('post/comment_single.html',{'comment':comment})
    # JsonResponse로 html를 ajax 요청한 페이지에 송신
    return JsonResponse({'html':html})
    return redirect(post)

    def comment_like(request, comment_id):
    # ajax 요청에서 is_ajax 데이터 수신
    is_ajax = request.POST.get("is_ajax")

    # ajax 요청한 데이터에 is_ajax 있는 경우
    if is_ajax:
    # 특정 comment_id를 pk값으로 갖고 있는 댓글을 comment로 설정
    comment = Comment.objects.get(pk=comment_id)
    # comment.like에 +1한 값을 다시 comment.like로 저장
    comment.like = comment.like + 1
    # 해당 comment 객체 저장
    comment.save()
    # JsonResponse로 'works'를 True로 설정하여 ajax 요청한 페이지에 송신
    return JsonResponse({'works':True})
    # ajax 요청한 데이터에 is_ajax 없는 경우, 현재 url로 이동
    return redirect('/')