2019.05.18 jquery & ajax를 활용하여 댓글 구현하기입니다.
- 패스트캠퍼스 웹 프로그래밍 스쿨 수업 정리 내용
목표
- 댓글을 달 때 ajax가 작동하여 새롭게 페이지가 리로드 되지 않게 하기
- ajax를 통해 단 댓글을 해당 DB에 저장하고
- 그 댓글만을 가지고와서 댓글창의 가장 상단에 끼워넣기
로직
- 먼저 해당 댓글 입렴 폼의 태그를 확인한다.
- 그리고 그 폼의 submit을 눌렀을 때 해당 변화가 없도록 막고
- submit의 경우 return false를 활용한다.
- url을 지정하고 serialize를 통해 현재 폼에 담겨져 있는 값들을 가지고 온다.
- ajax를 통해 url이 작동하도록 하고 해당 url을 views로 연결하여
- 해당 views.py(댓글 구현 뷰)에서 처리할 수 있도록 한다.
- 해당 뷰에서 처리 이후에 해당 채워넣을 부분의 html을 반환해줄 수 있도록 comment_single.html을 구현한다.
- 그리고 뷰에서 그 html파일을 JsonResponse를 통해 반환해준다.
- 다시 해당 템플릿에서 .done 부분에 prepend(가장 상단에 넣어주기)를 통해 해당 파일을 넣는다.
1. 해당 댓글 입력폼의 태그 확인하기
<form action="{ % url "board:comment" object.id % }" method="POST" id="comment_form">
{ % csrf_token % }
<input type="hidden" name="is_ajax" value="">
{{comment_form.as_p}}
<input type="submit" value="Comment" class="btn btn-outline-primary">
</form>
<table class="table table-striped" id="comment_list">
<tbody>
{ % for comment in comments % }
<tr>
<td>{{ comment.text }}</td>
<td>{{ comment.author.username}}</td>
<td>{{ comment.created }}</td>
<td><a href="{ % url 'board:comment_delete' comment.id % }">삭제하기</a></td>
<td><a href="{ % url 'board:comment_update' comment.id % }">수정하기</a></td>
</tr>
{ % endfor % }
</tbody>
</table>
2. 그 폼의 submit을 눌렀을 때 해당 변화가 없도록 막는다.
{ % block extra_script % }
<script type="text/javascript">
$(function () {
$('#comment_form').submit(function(e){
alert('댓글쓰기 완료');
return false; //이게 없으면 다시 리로드 되서 다녀온다.
});
});
</script>
{ % endblock % }
3. url을 지정하고 serialize를 통해 현재 폼에 담겨져 있는 값들을 가지고 온다.
- url의 경우 기존에 연결되어 있는 url을 활용한다.
- serialize를 통해 현재 폼에 담겨져 있는 값들을 가지고 온다.
4. views.py 완성하기
def comment(request, document_id):
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()
if is_ajax:
html = render_to_string('board/comment/comment_single.html',
{'comment':comment})
return JsonResponse({'html':html})
return redirect(document)
- is_ajax를 POST를 통해 is_ajax를 받는다. html의 jquery가 제대로 작동했다면 1을 가지고 있다.
- 해당 새롭게 생긴 댓글을 넣어주기 위한 간단한 html을 새롭게 제작한다.
- 만약 is_ajax가 있다면 html은 single.html을 rendering하고 위에 comment와 함께 넘겨줄 수 있도록 한다.
- JsonResponse를 통해 html을 넘겨준다.
comment/comment_single.html
<tr class="comment_row">
<td class="comment_text">{{ comment.text }}</td>
<td>{{ comment.author.username}}</td>
<td>{{ comment.created }}</td>
<td><a href="{ % url 'board:comment_delete' comment.id % }" class="btn_comment_delete">삭제하기</a></td>
<td><a href="{ % url 'board:comment_update' comment.id % }" class="btn_comment_update">수정하기</a></td>
</tr>
- 해당 페이지를 통해 가장 위에 끼워 넣을 댓글을 만들어낸다.
5. jquery 완성하기
{ % block extra_script % }
<script type="text/javascript">
$(function () {
$('#comment_form').submit(function(e){
$('input[name="is_ajax"]').val("1")
// alert('댓글쓰기 완료');
url = $(this).attr('action'); //원래 다녀와야하는 url
params = $(this).serialize(); //현재 폼에 담겨있는 값들을 가지고 올 수 있게 해준다.
$.ajax({
url:url,
method : "POST",
data: params,
}).done(function(data){
$('#id_text').val("");
$('#comment_list tbody').prepend(data.html); //tbody 시작지점에 요소 끼워넣기
//$('comment_list tbody').append(tr); //tbody 끝 지점에 요소 끼워넣기
// is_ajax 값 초기화
$('input[name="is_ajax"]').val("");
});
return false; //이게 없으면 다시 리로드 되서 다녀온다.
});
</script>
{ % endblock % }
- 해석하기
- comment_form이라는 id를 가진 곳에서 submit을 누르면 막는다.(e, return false)
- is_ajax라는 이름에 1의 값을 부여해준다.
- url은 원래 이동하는 url로 설정한다.
- params는 serialize()를 통해 현재 폼에 담겨 있는 값들을 가지고 올 수 있게 한다.
- ajax를 url 요청이 위에 정의해놓은 url로 왔을 때 그리고 method는 POST방식으로 왔을 때 작동한다.
- data는 params를 받는다.
- 위의 ajax를 통해 URLConf를 통해 views.py를 다녀오고 JsonResponse를 통해 해당 데이터를 반환 받는다.
- params도 views.py를 통해 data : params로 넣어서 보내준다.
- 야는 왜 id_text 값을 어디에서도 설정해주지 않았는데 적었던 데이터가 사라지는 것일까?
- 폼 형태로 끼워넣으면 알아서 id_text가 설정된다.
댓글달기 전체 과정보기
- submit이 일어나면 is_ajax를 1로 바꾼다.
- url 은 댓글남기기 페이지 주소를 가지고 온다.
- params = serialize를 통해 폼에 있는 데이터들을 하나로 붙인다.
- 리 다이렉션이 안되고 데이터를 추가로 가지고 오고 싶퍼서 is_ajax를 설정한 것이다.
- 뷰에서 is_ajax이 있으면 return Jsonresponse를 하고
- 아니면 redirect를 하도록 한다.