28、用所学知识实现点赞功能
1、点赞功能设计
- 1、博客和评论、回复可点赞
- 2、可取消点赞
- 3、可看到点赞总数
因为点赞是一个独立的功能模板,它可以加到任意位置,所以最好是新创建一个点赞app,
python manage.py startapp likes
,app创建完成后,到里面的models.py进行创建:
# # C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\likes\models.py
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):
# 这三个是描述ContentType的
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.py里面注册likes这个app:
然后迁移数据库
下一步,首先我们看一下前端页面,具体博客页面blog_detail.html
启动服务,刷新页面
调整css样式:
那么我们要先实现点赞完之后有变颜色的效果,这就涉及到一个onclick点击事件,要让它实现:如果没有点赞的状态,会变成点赞的状态,并且点赞数加1;如果是点赞的状态下,就要有取消点赞,并且点赞数减1。这一系列操作比较多,我们可以写成一个function,然后在这里调用就行
这里,我们前端页面暂时写到这个地方,等后端代码完成后再写完善前端页面
新建一个url路由,在likes下新建urls.py,写入如下代码:
# # C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\likes\urls.py
from django.urls import path
from . import views
urlpatterns = [
path('like_change', views.like_change, name='like_change')
]
另外,这个是加的应用的路由,我们还需要加到总的路由里面,修改mysite/urls.py如下:
路由配置完之后,前端页面就可以写入url了,提交数据到这个链接里面
另外,回头看一下models,models添加记录,需要提交content_type、object_id这两个数据,确定所点赞的对象(user可以通过request得到,我们这里就不需要提交这个数据),那么我们就可以继续完善html里面的data:
至此,前端页面又告一段落了,因为我们提交数据到后台这里没有任何的处理方法进行处理,只是提交了数据。那么就需要我们在后台处理方法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 SuccessResponse(liked_num):
data = {}
data['status'] = "SUCCESS"
data['liked_num'] = liked_num
return JsonResponse(data)
def ErrorResponse(code, message):
data = {}
data['status'] = 'ERROR'
data['code'] = code
data['message'] = message
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')
# is_like = request.GET.get('is_like')
# 处理数据
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文件夹,在该文件夹下面加一个_init__.py文件,然后新建likes_tags.py:
# # C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\likes\templatetags\likes_tags.py
from django import template
from django.contrib.contenttypes.models import ContentType
from ..models import LikeCount
register= template.Library() # 用于注册
@register.simple_tag # 将这个方法注册为simple_tag
def get_like_count(obj): # 传入obj这个对象,这个对象可以是任意类型。这里我们现在使用的是blog类型
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
重启服务没有问题
然后我们在前端页面使用它。修改blog_detail.html如下:
刷新页面,可以看到刚刚点赞过的地方 点赞数量加了1
同样的,在外面博客列表页面,我们也可以加上显示点赞数量,修改blog_list.html
刷新页面
回到之前的位置,我们点赞过之后,我们要在blog_detail页面对应位置动态判断加上active。这里我们是可以用后台处理方法做一个变量将它传进来,但这个处理方法是在博客里边 也就是blog应用里,如果我们在这里面写,会变得更加复杂。既然这里我们已经加了自定义模板标签, 那么我们可以考虑通过这个模板标签返回到底需不需要加active,新加一个自定义模板标签,修改likes_tags.py如下:
然后在blog_detail.html进行使用
刷新页面
我们继续完善前端页面blog_detail.html
完善二:对评论也有点赞功能
新增一个模板标签,获取对象的ContentType类型,修改likes_tags.py如下:
再修改blog_detail.html如下(复制点赞这块儿的html代码分别到评论和回复评论处,并修改对应的传给likes_tags.py新建的模板标签的obj参数 即对应的ContentType类型,因为之前的点赞这块html代码这里,给likeChange传入ContentType参数是直接写的‘blog’):
刷新页面,对评论和回复点赞测试一下:
2、前后端开发建议
功能需求分析 --> 模型设计 --> 前端初步开发 --> 后端实现 --> 完善前端代码
3、运用到所学什么知识
- Django基础(models、views、urls、…)
- ContentType
- ajax
- 自定义模板标签