파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.
이전 포스팅에서 장고 폼만으로 댓글 쓰기를 구현해보았다.
순수 웹문서의 형태로도 이와 같은 기능을 구현할 수 있으나, UI/UX 측면에서의 아쉬움이 남는다.
댓글을 작성한 이후 항상 상세 페이지로 리디렉션 된다는 점, 페이지가 다시 위로 올라간다는 점 등이 그러하다.
본 포스팅에서는 기존의 프로젝트에 jQuery를 붙여서 UI의 한 부분만 업데이트하도록 수정해본다.
jquery 및 jquery-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 플러그인 중 하나다. jQuery Form을 활용하면 HTML의 폼 제출 동작을 jQuery를 통해 손쉽게 해킹할 수 있다.
다음 문서를 참고하자: document link
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,
})
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-form의 ajaxSubmit
함수를 활용해서 비동기 폼을 제출을 구현한다.
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>