이번엔 Django와 axios를 이용해 좋아요 기능을 구현해보자
Like라는 모델은 각각 Post와 User의 1:N 관계이다.
class Like(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='%(class)s_post', null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='%(class)s_user', null=True, blank=True)
디테일 페이지로 들어왔을 때 해당 글의 좋아요를 클릭할 수 있다.
좋아요 버튼 클릭과 동시에 해당 글의 좋아요 수가 변경되고 좋아요 버튼의 색이 바뀌도록 구현해야 한다. 실시간으로 이벤트 처리를 해줘야 하므로 페이지가 렌더링이 되면 안된다. 결국 비동기 처리를 해줘야한다. 비동기 처리 방법 중 많은 선택지가 있지만 axios를 이용하기로 했다.
axios란 브라우저, Node.js를 위해서 만들어진 Promise API를 활용하는 HTTP 비동기 통신 라이브러리이다.
axios 요청을 보낼 때 method, url, data, config 등의 요청을 보낼 수 있다.
class LikeView(View):
model = Post
def get(self, request, *args, **kwargs):
post_id = request.GET.get('post_id')
userinfo = request.GET.get('userinfo')
user = get_object_or_404(User, username=request.user.username)
post = get_object_or_404(Post, pk=kwargs['pk'])
like = Like.objects.filter(user=request.user, post=post).first()
if like == None:
Like.objects.create(
post=post,
user=user
)
liked = True
return JsonResponse({"status": '200', 'liked': liked, 'count': post.like.count()})
else:
Like.objects.filter(user=user, post=post).delete()
liked = False
return JsonResponse({"status": '400', 'liked': liked, 'count': post.like.count()})
return JsonResponse({"status": 'Success'})
먼저 View를 상속받은 후 get 메서드를 정의한다.
만약 좋아요 버튼을 눌렀을 때 현재 접속한 유저와 해당 글에 해당하는 좋아요 객체가 없다면 생성시켜주고 이미 있다면 삭제시켜준다.
그리고 status 코드와 데이터를 JsonResponse로 응답해준다. Json 형태로 응답해주기 위해서는 딕셔너리 형태로 응답해주어야 정상적으로 응답이 가능하다.
# post_detail.html
{% extends 'base.html' %}
{% load static %}
{% block css %}
{% endblock %}
{% block content %}
<h1>Post Detail 페이지</h1>
<p>제목 : {{ target_post.title }}</p>
<p>내용 : {{ target_post.article }}</p>
<p>생성일 : {{ target_post.create_at }}</p>
<p>작성자 : {{ target_post.writer }}</p>
<form action="" method="get">
<button id="like" type="button" class="like">좋아요</button>
</form>
<br>
<span id="like-count-{{ target_post.id }}">{{ target_post.like.count }}</span>명이 좋아합니다
<br>
{% if target_post.writer == request.user.username %}
<a href="{% url 'crud:post_update' target_post.pk %}">글 수정하기</a><br>
<br>
<form action="{% url 'crud:post_delete' target_post.pk %}" method="post">
{% csrf_token %}
<button type="submit">글 삭제하기</button>
</form>
{% endif %}
{% endblock %}
템플릿에서 form에 get요청으로 데이터를 보낸다.
# post_detail.js
const likeBtn = document.querySelector('.like');
likeBtn.addEventListener('click', function (e) {
const postId = '{{ target_post.id }}';
const userInfo = '{{ request.user.id }}';
const url = `/list/${postId}/like`
const data = {
'post_id': postId,
'userinfo': userInfo
}
axios.get(url, data)
.then(function (response) {
document.querySelector(
`#like-count-${postId}`).innerText = response.data.count
console.log(response);
if (response.data.liked) {
e.target.className = 'like'
e.target.style.color = 'crimson'
} else {
e.target.className = 'like'
e.target.style.color = 'black'
}
})
.catch(function (error) {
console.log(error);
})
});
axios로 get 요청을 보낼 때 url, data를 함께 보낸다. 만약 post 요청시 csrf_token도 함께 보내야한다.
axios에서 get 요청을 보내면 django view에서 get 메서드로 상태 코드와 데이터를 보내준다. view에서 보내준 데이터를 받은 axios에서 정상적으로 응답을 받으면 .then 코드를 실행시키고 잘못된 응답을 받으면 .catch를 실행시킨다. 즉, 에러를 발생시킨다.
좋아요 버튼 클릭 시 텍스트의 색이 변경되고 좋아요 수가 변경되는 것을 볼 수가 있다.
스크립트 콘솔창을 살펴보면 어떤 데이터를 받는지 알 수 있다. view에서 넘겨준 상태코드와 데이터들이 넘어오고 status가 200으로 정상적으로 넘어오는 것을 볼 수가 있다.
'django' 카테고리의 다른 글
Django Admin 커스텀 (0) | 2022.11.22 |
---|---|
Django ORM (0) | 2022.03.09 |
Django CBV 기반 CRUD 만들기 (0) | 2022.01.09 |
Django 프로젝트 구조 (0) | 2021.12.07 |
Django Deploy (0) | 2021.12.07 |