jQuery를 통해 AJAX 댓글 쓰기 구현

guava·2022년 1월 9일
0

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.

이전 포스팅에서 장고 폼만으로 댓글 쓰기를 구현해보았다.
순수 웹문서의 형태로도 이와 같은 기능을 구현할 수 있으나, UI/UX 측면에서의 아쉬움이 남는다.
댓글을 작성한 이후 항상 상세 페이지로 리디렉션 된다는 점, 페이지가 다시 위로 올라간다는 점 등이 그러하다.

본 포스팅에서는 기존의 프로젝트에 jQuery를 붙여서 UI의 한 부분만 업데이트하도록 수정해본다.

Requirements


jQuery & jQuery-form 설치

jqueryjquery-form을 다운받아서 static에 추가한다.

jquery-3.6.0.min.js jquery.form.min-4.3.0.js

askcompany/static
├── bootstrap-4.6.1-dist
│   ├── css
│   │   ├── bootstrap-grid.css
│   │   ├── bootstrap-grid.css.map
│   │   ├── bootstrap-grid.min.css
│   │   ├── bootstrap-grid.min.css.map
│   │   ├── bootstrap-reboot.css
│   │   ├── bootstrap-reboot.css.map
│   │   ├── bootstrap-reboot.min.css
│   │   ├── bootstrap-reboot.min.css.map
│   │   ├── bootstrap.css
│   │   ├── bootstrap.css.map
│   │   ├── bootstrap.min.css
│   │   └── bootstrap.min.css.map
│   ├── icon
│   │   ├── heart-fill.svg
│   │   └── heart.svg
│   └── js
│       ├── bootstrap.bundle.js
│       ├── bootstrap.bundle.js.map
│       ├── bootstrap.bundle.min.js
│       ├── bootstrap.bundle.min.js.map
│       ├── bootstrap.js
│       ├── bootstrap.js.map
│       ├── bootstrap.min.js
│       └── bootstrap.min.js.map
├── jquery-3.6.0.min.js
├── jquery.form.min-4.3.0.js
└── logo.png

jQuery Form?

jQuery Form은 jQuery 플러그인 중 하나다. jQuery Form을 활용하면 HTML의 폼 제출 동작을 jQuery를 통해 손쉽게 해킹할 수 있다.

다음 문서를 참고하자: document link

jQuery를 활용한 비동기 댓글 쓰기 구현


Views

ajax요청이 올 때 랜더 화면의 comment-list에 추가 할 comment 블록을 생성해서 보내준다.

Template에서는 이 comment블록을 comment-list에 append해주어 부분 업데이트를 수행하게 된다.

# instagram/views.py

@login_required
def comment_new(request, post_pk):
    post = get_object_or_404(Post, pk=post_pk)
    if request.method == 'POST':
        form = CommentForm(request.POST, request.FILES)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.post = post
            comment.author = request.user
            comment.save()
            if request.is_ajax():  # ajax요청 시 응답
                return render(request, "instagram/_comment.html", {
                    "comment": comment
                })
            return redirect(comment.post)
    else:
        form = CommentForm()
    return render(request, 'instagram/comment_form.html', {
        'form': form,
    })

Templates

askdjango/templates/layout.html

layout.html에 jquery 패키지를 추가해준다.

...
<script src="{% static 'jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'jquery.form.min-4.3.0.js' %}"></script>
...

instagram/templates/instagram/_comment.html

comment_new에서 Response시 랜더 할 템플릿이다. 댓글 추가 시 상단에 추가되는 comment 블록이다.

{% load humanize %}
<div class="comment">
  <strong>{{ comment.author }}</strong>
  {{ comment.message }}
  <small class="text-muted">{{ comment.created_at|naturaltime }}</small>
</div>

instagram/templates/instagram/_post_card.html

jQuery-formajaxSubmit 함수를 활용해서 비동기 폼을 제출을 구현한다.

ajaxSubmit 함수에 대상 폼을 지정하기 위해 폼에 고유 id를 부여하였다. (post의 pk를 포함)

포스트 리스트 화면에서는 여러개의 post_card가 존재하기에 여러comment-list가 존재한다. 따라서 comment-list에도 고유 id를 부여하였다. (post의 pk를 포함)

ajaxSubmit 실행 후 응답을 comment-list에 추가해주는 작업을 수행하였다.

...
<div id="post-{{ post.pk }}-comment-list" class="comment-list mt-3 mb-3">
  {% for comment in post.comment_set.all %}
    {% include 'instagram/_comment.html' %}
  {% endfor %}
</div>

...

<form id="post-{{ post.pk }}-comment-form" action="{% url 'instagram:comment_new' post.pk %}" method="POST">
  {% csrf_token %}
  {% bootstrap_form comment_form %}
  {% buttons %}
    <button type="submit" class="btn btn-primary btn-block">
      댓글 쓰기
    </button>
  {% endbuttons %}
</form>

...

<script>
  jQuery(function () {
    var form_id = "post-{{ post.pk }}-comment-form";
    $("#" + form_id).submit(function (e) {
      e.preventDefault();
      var options = { // https://malsup.com/jquery/form/#ajaxSubmit
        success: function (responseText, statusText, xhr, $form) {
          console.group('ajaxSubmit response');
          console.log(responseText);
          console.log(statusText);
          console.log(xhr);
          console.log($form);
          console.groupEnd();
          $('#post-{{ post.pk }}-comment-list').prepend(responseText)
        }
      }
      $(this).ajaxSubmit(options);
    });
    console.log('document ready.');
  });
</script>

정리


  • jQuery 패키지를 프로젝트에 추가하였다.
  • ajaxSubmit 함수에 타겟 폼을 지정하고 응답 데이터를 comment-list class에 추가하도록 수정하였다.
  • 별도의 페이지 이동 없이 화면을 업데이트 하였다.

0개의 댓글