Django

Django ajax 좋아요 구현

til_t 2021. 1. 22. 14:13

 

models.py

 

from django.db import models
from django.urls import reverse

from taggit.managers import TaggableManager
from django.contrib.auth.models import User
from django.utils.text import slugify
from tinymce.models import HTMLField
from django.conf import settings

from user.models import Profile


class RecipeContent(models.Model):
    Rec_conId = models.AutoField(primary_key = True)
    # 글번호
    Rec_conName = models.CharField(verbose_name='TITLE', max_length=50)
    # 글제목
    Rec_conReadcount = models.IntegerField(default=0)
    # 조회수
    Rec_conCreate = models.DateTimeField('CREATE_TIME', auto_now_add=True)
    # 작성 시간
    Rec_conModify = models.DateTimeField('MODIFY_DATE')
    # 수정 시간
    Rec_conMemID = models.ForeignKey(User, on_delete=models.CASCADE,
                              verbose_name='OWNER', blank=True, null=True)
    # 작성자
    Rec_conPickCount = models.IntegerField(default=0)
    # 찜한 수
    Rec_conContent = HTMLField('CONTENT')
    # 글 내용
    Rec_conTags = TaggableManager(blank=True)
    # 글 태그
    Rec_conLikesUser = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        blank=True,
        related_name='Rec_conLikesUser'
    )

    class Meta:
        verbose_name = 'recipe_post'
        # verbose_name = 'recipe'
        # verbose_name_plural = 'recipes'
        ordering = ('-Rec_conModify',)  # orderby 절,

    def __str__(self):

      return self.Rec_conName

    def get_absolute_url(self):  # 현재 데이터의 절대 경로 추출

      return '' # reverse('recipe:recipe_detail', args=(self.pk,))
         # return reverse('blog:post_detail', args=(self.slug,))


    def get_previous(self):  # 이전 데이터 추출

      return self.get_previous_by_Rec_conModify()

    def get_next(self):  # 다음 데이터 추출

      return self.get_next_by_Rec_conModify()

    def get_recipe_summary(self):
        return self.Rec_conContent[:100]

    # 글의 100자까지만 잘라서 보여주기

    def rec_count_likes_user(self):
        return self.Rec_conLikesUser.count()



views.py

@login_required
@require_POST
def recipe_like(request):
    pk = request.POST.get('pk', None)
    recipe = get_object_or_404(RecipeContent, pk=pk)
    user = request.user

    if recipe.Rec_conLikesUser.filter(id=user.id).exists():
        recipe.Rec_conLikesUser.remove(user)
        if recipe.Rec_conPickCount == 0:
            recipe.Rec_conPickCount = 0
        else:
            recipe.Rec_conPickCount -= 1
        recipe.save()
        message = '좋아요 취소'
    else:
        recipe.Rec_conLikesUser.add(user)
        recipe.Rec_conPickCount += 1
        recipe.save()
        message = '좋아요'

    context = {'rec_likes_count':recipe.rec_count_likes_user(), 'message': message}
    return HttpResponse(json.dumps(context), content_type="application/json")


recipe_list.html

<a class="btn btn-sm rec_like" name="{{ recipe.Rec_conId }}" type="button" value="Like">


        {% if user in recipe.Rec_conLikesUser.all %}
        <i class="fas fa-heart" id="rec_heart{{ recipe.Rec_conId }}" style="color:#bd1f00"></i>
        {% else %}
        <i class="far fa-heart" id="rec_heart{{ recipe.Rec_conId }}" style="color:#bd1f00"></i>
        {% endif %}

<p id="rec_count-{{ recipe.Rec_conId }}" style="font:bold 1em;font-family:'바탕체';">
    좋아요&nbsp;{{ recipe.Rec_conLikesUser.all.count }}개</p>
</a><script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
    $(".rec_like").click(function () { // .like 버튼을 클릭 감지
        var pk = $(this).attr('name')
        $.ajax({ // ajax로 서버와 통신
            type: "POST", 
            url: "{% url 'recipe:recipe_like' %}", 
            data: { 'pk': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}' }, 
            dataType: "json",
            success: function (response) { 
                alert(response.message);
                $("#rec_count-" + pk).html("좋아요&nbsp;" + response.rec_likes_count + "개"); 
                if (response.message == "좋아요")
                   
                    {
                        $('#rec_heart' + pk).attr("class", "fas fa-heart")
                    } else if (response.message == "좋아요 취소")
                    
                    {
                        $('#rec_heart' + pk).attr("class", "far fa-heart")
                    }
            },
            error: function (request, status, error) { // 실패
                alert("로그인이 필요합니다.")
                window.location.replace("/accounts/login/") // 로그인 페이지로 넘어가기
            },
        });
    })



</script>