참고
stackoverflow: My own likes button
실습 저장소
https://github.com/JisunParkRea/djangotube_tutorial
구현하고자 하는 기능
- 마음에 드는 video에 '좋아요'를 누를 수 있게 하기
- ajax를 사용하여 웹페이지 새로고침 없이 좋아요 개수를 비동기적으로 업데이트하기
models.py
- Video는 여러 user로부터 likes를 받을 수 있고, user 또한 여러 Video에게 likes를 줄 수 있다: ManyToManyField
from django.conf import settings
from django.db import models
from django.conf import settings
class Video(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
video_key = models.CharField(max_length=12)
likes_user = models.ManyToManyField(
settings.AUTH_USER_MODEL, # this is preferred than just 'User'
blank=True, # blank is allowed
related_name='likes_user'
) # likes_user field
def count_likes_user(self): # total likes_user
return self.likes_user.count()
def __str__(self):
return self.title
urls.py
- like button을 눌렀을 때 상호작용할 수 있는 url을 만들어야 한다.
from django.urls import path
from . import views
urlpatterns = [
# ...
path('like/', views.video_like, name='video_like'),
]
views.py
- 로직을 구현해보자
- 로그인 한 사용자만이 likes button을 누를 수 있다: @login_required
- POST request만 받기로 하자: @require_POST
- likes button을 누르면 Video 모델의 likes_user 필드에 해당 user을 추가하자: .add()
- 이미 likes button을 누른 사용자가 또다시 누르면 좋아요 취소를 하자: .remove()
- ajax가 처리할 것은 좋아요의 개수와 알림 메세지이다. 이를 json 형태로 리턴하자: json.dumps()
import json
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
from .models import Video
@login_required
@require_POST
def video_like(request):
pk = request.POST.get('pk', None)
video = get_object_or_404(Video, pk=pk)
user = request.user
if video.likes_user.filter(id=user.id).exists():
video.likes_user.remove(user)
message = '좋아요 취소'
else:
video.likes_user.add(user)
message = '좋아요'
context = {'likes_count':video.count_likes_user(), 'message': message}
return HttpResponse(json.dumps(context), content_type="application/json")
template(video_detail.html)
<!-- ...생략 -->
<div>
<input type="button" class="btn btn-info btn-sm like" name="{{ video.id }}" value="Like"
style="margin-top: 7px">
<p id="count-{{ video.id }}" style="font:bold 1em; margin-top: 3px">
좋아요 {{ video.likes_user.all.count }}개</p>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$(".like").click(function () { // .like 버튼을 클릭 감지
var pk = $(this).attr('name')
$.ajax({ // ajax로 서버와 통신
type: "POST", // 데이터를 전송하는 방법
url: "{% url 'video_like' %}", // 통신할 url을 지정
data: { 'pk': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}' }, // 서버로 데이터 전송시 옵션, pk를 넘겨야 어떤 video인지 알 수 있음
dataType: "json",
success: function (response) { // 성공
alert(response.message);
$("#count-" + pk).html("좋아요 " + response.likes_count + "개"); // 좋아요 개수 변경
},
error: function (request, status, error) { // 실패
alert("로그인이 필요합니다.")
window.location.replace("/video/login/") // 로그인 페이지로 넘어가기
},
});
})
</script>
결과