dgango-博客項目之點贊與評論

一、點贊和踩滅

1、事務

事務:要麼同時發生,要麼同時不發生,文章點贊表增加一條數據的時候,對應的文章的點贊或者踩滅數加1,如果後面的if語句不能執行,則根據事務,點贊表也不會增加數據

from django.db import transaction                                                         #引入transaction事務

with transaction.atomic():
    obj = ArticleUpDown.objects.create(user_id=user_pk, article_id=article_id, is_up=is_up)    #文章點贊表裏面添加一條數據
    if is_up:
        Article.objects.filter(pk=article_id).update(up_count=F("up_count") + 1)            #文章表相應的文章的點贊數加1
    else:
        Article.objects.filter(pk=article_id).update(down_count=F("down_count") + 1)       #文章表相應的文章的踩滅數加1


2、render方法

瀏覽器給服務器發送一個請求,視圖函數從模板中取到html頁面,如果頁面裏面有模板語法,如{{ }}、{% %},render方法會先對其進行渲染,將模板語法替換爲相應的html標籤,

最後將標籤返回給瀏覽器,所以如果js在html頁面,那麼就可以使用模板語法,而如果將js單獨做成一個靜態文件,則不能使用模板語法。


3、點讚的視圖函數和頁面

views.py文件增加點贊視圖:

import json
from django.http import JsonResponse
from django.db.models import F
from django.db import transaction
def digg(request):
    res={"state":True}                     #狀態爲true代表點贊,false爲踩滅
    user_pk=request.user.pk                 # 當前登錄用戶,即點贊用戶,request.user是全局變量
    article_id=request.POST.get("article_id")
    is_up=request.POST.get("is_up")             #因爲js默認post是urlencode,發送的是字符串,所以這裏接收到的就是字符串
    is_up=json.loads(is_up)                #將收到的字符串通過json序列化爲我們需要的布爾值
    try:
        with transaction.atomic():          #事務
            obj=ArticleUpDown.objects.create(user_id=user_pk,article_id=article_id,is_up=is_up)
            if is_up:
                 Article.objects.filter(pk=article_id).update(up_count=F("up_count")+1)
            else:
                 Article.objects.filter(pk=article_id).update(down_count=F("down_count") + 1)
    except Exception as e:
        res["state"]=False                #變成踩滅狀態
        res["first_action"]=ArticleUpDown.objects.filter(user_id=user_pk,article_id=article_id).first().is_up  #返回給ajax的數據多了first_action屬性
    return JsonResponse(res)                   #返回給ajax的時候,ajax不用反序列化,接收到的是一個字典格式


article_detail.html頁面:

{% extends "base.html" %}

{% block content %}
    <h3 class="text-center">{{ article_obj.title }}</h3>
    <div class="article_content">
        {{ article_obj.articledetail.content|safe }}
    </div>
    <div class="poll clearfix">
        <div id="div_digg" class="clearfix">
            <div class="diggit action">
                <span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
            </div>
            <div class="buryit action">
                <span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
            </div>
            <div class="clear"></div>
        </div>
    </div>
    <div class="diggword" id="digg_tips" style="color: red;"></div>
    <div class="info" article_id="{{ article_obj.pk }}" username="{{ request.user.username }}"></div>     {#爲了在靜態文件article_detail.js中取到html頁面的變量#}
    {% csrf_token %}
    <script src="/static/js/article_detail.js"></script>
{% endblock %}


因爲我們的html是繼承的base.html頁面,所有要在base.html頁面引入
<link rel="stylesheet" href="/static/css/article_detail.css">


article_detail.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;
}


article_detail.js代碼:

$(".action").click(function () {
    if ($(".info").attr("username")) {                                      //表示當前用戶登錄
        var is_up;
        is_up = $(this).hasClass("diggit");
        article_id = $(".info").attr("article_id");                            //根據屬性查找取到article_detail.html頁面article_id的值
        //
        $.ajax({
            url: "blog/digg/",
            type: "post",
            data: {
                is_up: is_up,
                article_id: article_id,
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()     //防止出現404 forbidden錯誤
            },
            success: function (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 {                          //重複提交
                    console.log(data.first_action);
                    if (data.first_action) {
                        $("#digg_tips").html("您已經推薦過了");
                        setTimeout(function () {                        // 1秒後下面的消息不顯示
                            $("#digg_tips").html("");
                        }, 1000)
                    }
                    else {
                        $("#digg_tips").html("您已經反對過了");
                        setTimeout(function () {
                            $("#digg_tips").html("");
                        }, 1000)
                    }
                }
            }
        })
    }
    else{                                                          //用戶必須登錄後才能進行點贊、踩滅
        # var s="<a href='/login/' class='pull-right'>請登陸!</a>";
        # $("#div_digg").after(s);                                 //返回給用戶“請登陸”信息
        location.href = "/login/?next=" + location.pathname       //直接調轉到用戶登錄頁面
    }
});


二、評論

1、js取標籤裏的值

select標籤                .val();
input標籤                 .val();
textarea標籤              .val();
div標籤、span標籤取裏面值的時候用.html()或.text();

2、評論樓:

article_detail.html頁面:

{% extends "base.html" %}

{% block content %}
    <h3 class="text-center">{{ article_obj.title }}</h3>
    <div class="article_content">
        {{ article_obj.articledetail.content|safe }}
    </div>
    <ul class="comment_list list-group">
        評論樓:
        {% for comment in comment_list %}
            <li class="comment_item list-group-item">
                <div>
                    <a href="">#{{ forloop.counter }}</a>樓 &nbsp;&nbsp;&nbsp;
                    <span>{{ comment.create_time|date:"Y-m-d H:i" }}</span>&nbsp;&nbsp;                    {#顯示時間,格式爲年-月-日 時:分#}
                    <span>{{ comment.user.username }}</span>                                               {#評論人,當前評論的評論名#}
                    <a class="pull-right reply_btn" username="{{ comment.user.username }}"
                       comment_id="{{ comment.pk }}"><span>回覆</span></a>
                </div>
                {% if comment.parent_comment_id %}                                                           {#評論是子評論#}
                        <div class="parent_comment_infon well">
                             @{{ comment.parent_comment.user.username }}&nbsp;:&nbsp;{{ comment.parent_comment.content }}<br/>
                             {{ comment.content }}
                        </div>
                {% else %}                                                                                {#評論是根評論#}
                        <div class="comment_con">
                            <p>{{ comment.content }}</p>
                        </div>
                {% endif %}
            </li>
        {% endfor %}
    </ul>
    <div class="comment">
        <div>
            暱稱:
            <input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50"
                   value="{{ request.user.username }}">
        </div>
        <div>
            <p>評論內容</p>
            <textarea name="" id="comment_content" cols="115" rows="10"></textarea>
        </div>
        <button class="btn  btn-default comment_btn">提交</button>
    </div>
    <div class="info" article_id="{{ article_obj.pk }}" username="{{ request.user.username }}"></div>
    {% csrf_token %}
    <script>
        var pid = "";
        $(".comment_btn").click(function () {                           // 提交評論事件
            article_id = $(".info").attr("article_id");                //在頁面根據屬性查找得到當前文章id號
            content = $("#comment_content").val();                    //textarea標籤通過.val()得到裏面的值
            // 處理文本框內容
            if (pid) {
                var index = content.indexOf("\n");                      //得到\n換行符的索引
                content = content.slice(index + 1)                       //換行符的索引加1的位置即我們所需要文本內容的開始位置
            }
            $.ajax({
                url: "/blog/comment/",
                type: "post",
                data: {
                    article_id: article_id,
                    content: content,
                    pid: pid,                                        //pid爲空,則提交根評論
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
                },
                success: function (data) {                          //視圖函數comment返回的數據
                    console.log(data);
                    ctime = data.ctime;
                    content = data.content;
                    username = $(".info").attr("username");       //從頁面取到評論人的名字
                    s = '<li class="comment_item list-group-item temp"> <div> <span>' + ctime + '</span>&nbsp;&nbsp;<span>' + username + '</span> </div> <div class="comment_con"><p>' + content + '</p></div> </li>'
                    $(".comment_list").append(s);
                    $("#comment_content").val("");                //提交成功後,清空評論框裏面的評論內容
                    pid = "";                                         //pid重新置空,這樣接着在評論框裏評論就變成了根評論,否則提交一直是子評論
                }
            })
        });
        $(".reply_btn").click(function () {                    // 回覆按鈕事件
            $("#comment_content").focus();                     // 獲取輸入框的焦點
            var val = "@" + $(this).attr("username") + "\n";
            $("#comment_content").val(val);
            pid = $(this).attr("comment_id")
        })
    </script>
    <script src="/static/js/article_detail.js"></script>
{% endblock %}

article_detail.css代碼:

input.author {
    background-image: url("/static/img/icon_form.gif");
    background-repeat: no-repeat;
    border: 1px solid #ccc;
    padding: 4px 4px 4px 30px;
    width: 300px;
    font-size: 13px;
}
.comment_item .comment_con{
    margin-top: 10px;
    margin-left: 20px;
}
.conmment_item{
    margin-left: 20px;
}
.comment {
    width: 820px;
}
.parent_comment_infon{
    position: relative;
    margin: 0 40px 0 40px;
    border: #ccc 1px dashed;
    padding: 1px;
    color: grey;
    font-family: Arial,Helvetica,sans-serif;
    font-size: 12px;
    font-weight: normal;
    text-decoration: none;
}
.comment_con{
    position: relative;
    margin: 0 10px 0 10px;
    border: #ccc 1px dashed;
    padding: 5px;
    color: black;
    font-family: Arial,Helvetica,sans-serif;
    font-size: 15px;
    font-weight: normal;
    text-decoration: none;
}
.temp {
    background-color: gainsboro;
}

views.py文件增加評論樓視圖:

# 評論
def comment(request):
    user_pk=request.user.pk
    article_id=request.POST.get("article_id")
    content=request.POST.get("content")
    pid=request.POST.get("pid")
    response={}
    with transaction.atomic():                   #事件
        if not pid:                              # pid爲空表示根評論
            comment_obj=Comment.objects.create(user_id=user_pk,article_id=article_id,content=content)                          # 提交根評論
        else:                                     # 子評論
            comment_obj = Comment.objects.create(user_id=user_pk, article_id=article_id, content=content,parent_comment_id=pid)  # 提交子評論
        Article.objects.filter(pk=article_id).update(comment_count=F("comment_count")+1)
    response["ctime"]=comment_obj.create_time.strftime("%Y-%m-%d %H:%M")           #返回給ajax的創建時間,時間格式爲%Y-%m-%d %H:%M
    response["content"]=comment_obj.content                                          #返回給ajax的評論內容
    return JsonResponse(response)
def article_detail(request,username,article_id):
    user = UserInfo.objects.filter(username=username).first()      # 查當前站點的用戶對象
    blog = user.blog
    article_obj=Article.objects.filter(pk=article_id).first()
    comment_list=Comment.objects.filter(article_id=article_id)
    return render(request,"article_detail.html",locals())

評論.png

3、評論樹:

article_detail.html頁面添加評論樹代碼:

    <div class="comment_tree">
        <p>評論樹</p>
    </div>
    <script>
        // 獲取評論信息,以評論樹形式展示
        $.ajax({
            url: "/blog/comment_tree/" + $(".info").attr("article_id"),
            success: function (comment_list) {
                console.log(comment_list);
                html = "";
                $.each(comment_list, function (index, comment_dict) {
                    var comment_pk=comment_dict["pk"]
                    var comment_content=comment_dict["content"]
                    temp= '<div comment_tree_id='+comment_pk+' class="conmment_item"> <span class="content">'+comment_content+'</span></div>'
                    if (!comment_dict.parent_comment_id) {                           // 沒有父評論,即根評論
                         $(".comment_tree").append(temp)}
                    else {                                                                                   // 子評論處理
                        var pid=comment_dict.parent_comment_id;
                        $("[comment_tree_id="+pid+"]").append(temp)
                    }
                });
            }
        });
    </script>


views.py文件增加評論樹視圖函數:

def comment_tree(request,article_id):
    comment_list=list(Comment.objects.filter(article_id=article_id).values("content","pk","parent_comment_id"))
    print(comment_list)
    return JsonResponse(comment_list,safe=False)                #JsonResponse返回的是列表,需要參數safe=False處理



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章