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:'바탕체';">
좋아요 {{ 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("좋아요 " + 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>