1、點贊和踩滅css
一、事務html
事務:要麼同時發生,要麼同時不發生,文章點贊表增長一條數據的時候,對應的文章的點贊或者踩滅數加1,若是後面的if語句不能執行,則根據事務,點贊表也不會增長數據python
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
二、render方法git
瀏覽器給服務器發送一個請求,視圖函數從模板中取到html頁面,若是頁面裏面有模板語法,如{{ }}、{% %},render方法會先對其進行渲染,將模板語法替換爲相應的html標籤,ajax
最後將標籤返回給瀏覽器,因此若是js在html頁面,那麼就可使用模板語法,而若是將js單獨作成一個靜態文件,則不能使用模板語法。django
三、點讚的視圖函數和頁面json
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樣式代碼:app
#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 //直接調轉到用戶登陸頁面 } });
2、評論
一、js取標籤裏的值
select標籤 .val(); input標籤 .val(); textarea標籤 .val(); div標籤、span標籤取裏面值的時候用.html()或.text();
二、評論樓:
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>樓 <span>{{ comment.create_time|date:"Y-m-d H:i" }}</span> {#顯示時間,格式爲年-月-日 時:分#} <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 }} : {{ 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> <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())
三、評論樹:
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處理