点赞模块示例

 

点赞就是当前登录人

一、流程分析:

  1 绑定事件
  2 携带data={article_id,is_up}发送Ajax请求
  3 对应的视图函数要生成一个赞或者灭记录
  4 响应结果给ajax
  5 Ajax的success处理

二、功能实现

点赞表

class ArticleUpDown(models.Model):
    """
    点赞表
    """
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to="UserInfo", null=True)
    article = models.ForeignKey(to="Article", null=True)
    is_up = models.BooleanField(default=True)

    class Meta:
        unique_together = (("article", "user"),)
        verbose_name = "文章点赞"
        verbose_name_plural = verbose_name

文章点赞模块article_detail.html 

<div id="div_digg">
        <div class="diggit action">
            <span class="diggnum" id="digg_count">{{ article.up_count }}</span>
        </div>
        <div class="buryit action">
            <span class="burynum" id="bury_count">{{ article.down_count }}</span>
        </div>
        <div class="clear"></div>
        <div class="diggword" id="digg_tips" style="color: red;"></div>
    </div>
<div class="info" article_id="{{ article.pk }}" username="{{ request.user.username }}"></div> {% csrf_token %} <script src="/static/js/article_detail.js"></script> 

对应mystyle.css

#div_digg {
    float: right;
    margin-bottom: 10px;
    margin-right: 30px;
    font-size: 12px;
    width: 125px;
    text-align: center;
    margin-top: 10px;
}

.diggit {
    float: left;
    width: 46px;
    height: 52px;
    background: url("/static/img/upup.gif") no-repeat;
    text-align: center;
    cursor: pointer;
    margin-top: 2px;
    padding-top: 5px;
}
.buryit {
    float: right;
    margin-left: 20px;
    width: 46px;
    height: 52px;
    background: url("/static/img/downdown.gif") no-repeat;
    text-align: center;
    cursor: pointer;
    margin-top: 2px;
    padding-top: 5px;
}

.clear {
    clear: both;
}
/*当属性设置float(浮动)时,他所在的物理位置已经脱离文档流了,但是大多时候我们希望文档流能识别float(浮动),
或者是答希望float(浮动)后面的元素不被float(浮动)所影响,这个时候我们就需要用clear:both;来清除。*/

1、绑定事件、携带data数据发送Ajax请求article_detail.js

$("#div_digg .action").click(function () {
    // 判断用户是否登录,如果已经登录:
    if ($(".info").attr("username")) {

        // 点赞或踩灭
        var is_up = $(this).hasClass("diggit");
        var article_id = $(".info").attr("article_id");

        $.ajax({
            url: "/blog/up_down/",
            type: "post",
            data: {
                //不用传user,因为用户只要登录就可以从request.user中取到
                is_up: is_up,
                article_id: article_id,
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
            },
        })
    }
    // 如果用户没有登录,返回登录界面进行登录
    else {
        location.href = "/login/"
    }
}); 

2 对应的视图函数views.py,生成一个赞或者灭记录,把响应结果传给Ajax

    url(r"up_down/",views.up_down), 
import json
from django.db.models import F

def up_down(request):
    print(request.POST)
    #有人点赞时传过来的值
    #<QueryDict: {'is_up': ['true'], 'article_id': ['6'],
    # 'csrfmiddlewaretoken': ['SL5W1m2Bb9fw5lsirkoEmB2wnvvWjMeSaE3WRxR6URkR0K9bDJCSto2fhVmAUOCa']}>
    article_id=request.POST.get('article_id')
    is_up=json.loads(request.POST.get('is_up'))
    #is_up在js中取出来的是布尔值,但是在前端当成键值以字符串的形式传过来
    #而is_up在数据库表中只能存TRUE or FALSE ,所以这里要把传过来的字符串通过json.loads转为python对象的布尔值
    user=request.user
    response={"state":True}
    print("is_up",is_up)      #is_up True
    try:
        #创建一条点赞记录
        models.ArticleUpDown.objects.create(user=user,article_id=article_id,is_up=is_up)
        #根据article_id找到点赞的那篇文章,更新点赞数
        models.Article.objects.filter(pk=article_id).update(up_count=F("up_count")+1)

    except Exception as e:
        response["state"]=False
        #第二次点此时user=user,article_id=article_id已经存在(联合唯一导致报错),取出里面的值(第一次存的)
        response["fisrt_action"]=models.ArticleUpDown.objects.filter(user=user,article_id=article_id).first().is_up

    return JsonResponse(response) 
    #return HttpResponse(json.dumps(response))

3 Ajax拿到响应结果,进行success处理article_detail.js 

success: function (data) {
        console.log(data);  //   {state: true}

        if (data.state) {// 赞或者灭成功

            if (is_up) {
                //如果是赞取出赞的计数文本内容进行自加1然后赋值回去
                var val = $("#digg_count").text();
                val = parseInt(val) + 1;
                $("#digg_count").text(val);
            } else {
                var val = $("#bury_count").text();
                val = parseInt(val) + 1;
                $("#bury_count").text(val);
            }
        }
        else {    // 重复提交

            if (data.fisrt_action) {
                $("#digg_tips").html("您已经推荐过");
            } else {
                $("#digg_tips").html("您已经反对过");
            }

            setTimeout(function () {
                $("#digg_tips").html("")
            }, 1000)
        }
    } 

完整的article_detail.js文件

$("#div_digg .action").click(function () {
    // 判断用户是否登录,如果已经登录:
    if ($(".info").attr("username")) {

        // 点赞或踩灭
        var is_up = $(this).hasClass("diggit");
        var article_id = $(".info").attr("article_id");

        $.ajax({
            url: "/blog/up_down/",
            type: "post",
            data: {
                //不用传user,因为用户只要登录就可以从request.user中取到
                is_up: is_up,
                article_id: article_id,
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
            },
            success: function (data) {
                console.log(data);


                if (data.state) {// 赞或者灭成功

                    if (is_up) {
                        var val = $("#digg_count").text();
                        val = parseInt(val) + 1;
                        $("#digg_count").text(val);
                    } else {
                        var val = $("#bury_count").text();
                        val = parseInt(val) + 1;
                        $("#bury_count").text(val);
                    }
                }
                else {    // 重复提交

                    if (data.fisrt_action) {
                        $("#digg_tips").html("您已经推荐过");
                    } else {
                        $("#digg_tips").html("您已经反对过");
                    }

                    setTimeout(function () {
                        $("#digg_tips").html("")
                    }, 1000)
                }
            }
        })

    }
    // 如果用户没有登录,返回登录界面进行登录
    else {
        location.href = "/login/"
    }

});
原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/12842307.html