因为点赞功能应该属于一个比较独立的功能键,所以新创建一个app:likes
python manage.py startapp likes
likes/models.py中创建LikeCount模型类,创建LikeRecord模型类
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
class LikeCount(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
liked_num = models.IntegerField(default=0)
class LikeRecord(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
user = models.ForeignKey(User, on_delete=models.CASCADE)
liked_time = models.DateTimeField(auto_now_add=True)
在settings中注册likes这个app
迁移数据库
写前端代码:
blog_detail.html中在评论下面增加图标:
使点赞之后大拇指图变成红色:
# likes/views.py
from django.shortcuts import render
from django.contrib.contenttypes.models import ContentType
from django.http import JsonResponse
from django.db.models import ObjectDoesNotExist
from .models import LikeCount, LikeRecord
def ErrorResponse(code, message):
data = {}
data['status'] = 'ERROR'
data['code'] = code
data['message'] = message
return JsonResponse(data)
def SuccessResponse(liked_num):
data = {}
data['status'] = 'SUCCESS'
data['liked_num'] = liked_num
return JsonResponse(data)
def like_change(request):
# 获取数据
user = request.user
if not user.is_authenticated:
return ErrorResponse(400, 'you were not login')
content_type = request.GET.get('content_type')
object_id = int(request.GET.get('object_id'))
try:
content_type = ContentType.objects.get(model=content_type)
model_class = content_type.model_class()
model_obj = model_class.objects.get(pk=object_id)
except ObjectDoesNotExist:
return ErrorResponse(401, 'object not exist')
# 处理数据
if request.GET.get('is_like') == 'true':
# 要点赞
like_record, created = LikeRecord.objects.get_or_create(content_type=content_type, object_id=object_id, user=user)
if created:
# 未点赞过,进行点赞
like_count, created = LikeCount.objects.get_or_create(content_type=content_type, object_id=object_id)
like_count.liked_num += 1
like_count.save()
return SuccessResponse(like_count.liked_num)
else:
# 已点赞过,不能重复点赞
return ErrorResponse(402, 'you were liked')
else:
# 要取消点赞
if LikeRecord.objects.filter(content_type=content_type, object_id=object_id, user=user).exists():
# 有点赞过,取消点赞
like_record = LikeRecord.objects.get(content_type=content_type, object_id=object_id, user=user)
like_record.delete()
# 点赞总数减1
like_count, created = LikeCount.objects.get_or_create(content_type=content_type, object_id=object_id)
if not created:
like_count.liked_num -= 1
like_count.save()
return SuccessResponse(like_count.liked_num)
else:
return ErrorResponse(404, 'data error')
else:
# 没有点赞过,不能取消
return ErrorResponse(403, 'you were not liked')
然后在likes中创建templatetags的python包,新增likes_tags.py文件
# likes_tags.py
from django import template
from django.contrib.contenttypes.models import ContentType
from ..models import LikeCount, LikeRecord
register = template.Library()
@register.simple_tag
def get_like_count(obj):
content_type = ContentType.objects.get_for_model(obj)
like_count, created = LikeCount.objects.get_or_create(content_type=content_type, object_id=obj.pk)
return like_count.liked_num
@register.simple_tag(takes_context=True)
def get_like_status(context, obj): # 加入context可以获取所在模板页面的所有变量
"""
获取是否点赞的状态
"""
content_type = ContentType.objects.get_for_model(obj)
user = context['user']
if not user.is_authenticated: # 判断是否登录
return ''
if LikeRecord.objects.filter(content_type=content_type, object_id=obj.pk, user=user).exists():
return 'active'
else:
return ''
@register.simple_tag
def get_content_type(obj): # 用于让前端使用模板标签
content_type = ContentType.objects.get_for_model(obj)
return content_type.model
然后再blog_detail.html中导入并渲染likes_tags中的提取到的内容:
继续完善点赞功能:blog_detail.html的代码
{% extends 'base.html' %}
{% block title %}{{ blog.title }}{% endblock %}
{% block nav_blog_active %}active{% endblock %}
{% load static %}
{% load comment_tags %}
{% load likes_tags %}
{% block header_extends %}
{% endblock %}
{# 页面内容 #}
{% block content %}
{{ blog.title }}
- 作者:{{ blog.author }}
- 分类:{{ blog.blog_type }}
- 发表日期:{{ blog.created_time|date:"Y-m-d H:i:s" }}
- 阅读量:{{ blog.get_read_num }}
- 评论数:{% get_comment_count blog %}
{{ blog.content|safe }}
{% get_like_count blog %}
喜欢
上一篇:
{% if previous_blog %}
{{ previous_blog.title }}
{% else %}
没有了
{% endif %}
下一篇:
{% if next_blog %}
{{ next_blog.title }}
{% else %}
没有了
{% endif %}
评论列表
{% get_comment_list blog as comments %}
{% for comment in comments %}
{{ comment.user.username }}
({{ comment.comment_time|date:"Y-m-d H:i:s" }}):
{{ comment.text|safe }}
{% get_like_count comment %}
回复
{% for reply in comment.root_comment.all %}
{{ reply.user.username }}
({{ reply.comment_time|date:"Y-m-d H:i:s" }})
回复
{{ reply.reply_to.username }}:
{{ reply.text|safe }}
{% get_like_count reply %}
回复
{% endfor %}
{% empty %}
暂无评论
{% endfor %}
{% endblock %}
{% block script_extends %}
{% endblock %}
提交评论
{% if user.is_authenticated %} {% else %} 您尚未登录,登录之后方可评论~ 登录 or 注册 {% endif %}