一、點贊功能設計
1、博客、評論、回復可點贊
2、可取消點贊
3、可看到點贊數
前端設計
<div class="like" onclick="likeChange(this,'{% get_content_type blog %}',{{ blog.pk }})"> <span class="glyphicon glyphicon-thumbs-up {% get_likes_status blog %}"></span> <span class="liked-num">{% get_like_count blog %}</span> <span>喜歡</span> </div>
function likeChange(obj, content_type, object_id){ var is_like = obj.getElementsByClassName('active').length == 0 $.ajax({ url: "{% url 'like_change' %}", type: 'GET', data: { content_type: content_type, object_id: object_id, is_like: is_like }, cache: false, success: function(data){ console.log(data) if(data['status']=='SUCCESS'){ //更新點贊狀態 var element = $(obj.getElementsByClassName('glyphicon')); if(is_like){ element.addClass('active'); }else { element.removeClass('active'); } //更新點贊數量 var liked_num = $(obj.getElementsByClassName('liked-num')); liked_num.text(data['liked_num']); }else { alert(data['message']); } }, error: function(xhr){ console.log(xhr) } }); }
模型設計
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): # 將您的模型ForeignKey 設為ContentType 通過ContentType找到具體的模型 content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() # 記錄對應模型的主鍵值 該字段可以存儲您將要關聯的模型中的主鍵值 # 給您的模型一個 GenericForeignKey,並為其傳遞上述兩個字段的名稱。如果將這些字段分別命名 # 為“ content_type”和“ object_id”,則可以忽略這些-這些是默認字段名稱 GenericForeignKey。 content_object = GenericForeignKey('content_type', 'object_id') liked_num = models.IntegerField(default=0) #具體誰對哪個對象點贊,點贊記錄 class LikeRecord(models.Model): #保存被點贊對象這個信息 # 將您的模型ForeignKey 設為ContentType 通過ContentType找到具體的模型 content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() # 記錄對應模型的主鍵值 該字段可以存儲您將要關聯的模型中的主鍵值 # 給您的模型一個 GenericForeignKey,並為其傳遞上述兩個字段的名稱。如果將這些字段分別命名 # 為“ content_type”和“ object_id”,則可以忽略這些-這些是默認字段名稱 GenericForeignKey。 content_object = GenericForeignKey('content_type', 'object_id') user = models.ForeignKey(User, on_delete=models.CASCADE) liked_time = models.DateTimeField(auto_now_add=True)
路由
from django.urls import path from . import views urlpatterns = [ path('like_change',views.like_change,name='like_change'), ]
后端實現
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')
自定義模版標簽,獲取點贊數量,獲取點贊狀態用來實時顯示狀態,獲取對象的content_type模型
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 #takes_context=True可以獲取所在模版頁面的模版變量 @register.simple_tag(takes_context=True) def get_likes_status(context, obj): 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=context['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
二、前后端開發建議
功能需求分析——模型設計——前端初步開發——后端實現——完善前端代碼