由於做博客園系統的時候發現評論功能的實現耗費蠻長時間,比較適合練習,遂整理如下:
評論分為:對文章的評論和對評論的評論。
有兩種方式實現多級評論,一種類似博客園特色的評論方式,蓋樓@某位用戶。一種采用樹形結構實現,涉及一個很重要的點:字典和列表是引用數據類型,或者說可變類型;字典的鍵必須是不可變類型(可以是整型)。
主要整理第二種,學習數據結構的設計思想:
評論結構:

數字代表評論的ID號,由一張專門的comment表存放。
1,2,3,9為根級評論,代表對文章的評論,其余為子評論,代表對父級評論的評論。
class Comment(models.Model):
'''
一篇文章可以有多個評論,一條評論只能屬於一篇文章;
一個用戶可以有多條評論,一條評論只能屬於一個用戶;
評論還可以有評論;
還有一個字段存放用戶評論時間;
評論點贊次數;
'''
commentInfo=models.CharField(max_length= 200,verbose_name= "評論內容")
article=models.ForeignKey("Article",verbose_name= "評論文章")
user=models.ForeignKey("UserInfo",verbose_name= "評論人")
parent_id=models.ForeignKey("self",verbose_name= "父級評論",null=True) #做了修改
create_time=models.DateTimeField(verbose_name= "評論時間",auto_now_add= True)
# 設置評論被贊的次數
up_count=models.IntegerField(default= 0)
def __str__(self):
return self.commentInfo
# 通過評論找文章:(正向)article_obj=comment_obj.article
# 通過文章找評論:(反向)article_obj.comment_set.all
# 通過評論找到評論用戶:(正向)comment_obj.user
代碼實現:
方式一:


方式二:


推薦方式二:盡量避免for循環嵌套for循環方式,優化性能。
評論功能實現要點記錄:
第一點:點擊評論可以直接定位到評論輸入框,技術實現:錨點或者前端的scrollIntoView()用法。
第二點:評論區采用富文本編輯框Kindeditor。注意上傳文件以及路徑配置。詳細參考官網文檔:http://kindeditor.net/doc.php
主要代碼截取:
#############views.py#############
def upload_file(request):
if request.method == "POST":
file_obj = request.FILES.get("imgFile")
print(file_obj, type(file_obj)) # 1.jpg <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
print(file_obj.name, type(file_obj.name)) # 1.jpg <class 'str'>
file_name = file_obj.name
file_path = os.path.join("blog/media/upload/img/", file_name) # blog/media/upload/img/1.jpg
print(file_path)
with open(file_path, "wb") as f:
for chunk in file_obj.chunks():
f.write(chunk)
response_put = {
"error": 0,
"url": "/media/upload/img/" + file_name, # 特別注意路徑問題
}
return HttpResponse(json.dumps(response_put))
##################templates之articledetail.html################## <form> {% csrf_token %} <h5>評論:</h5> <div id="contentArea2"> <textarea cols="60" rows="10" id="contentArea"> {# 試了,name不可以 #} </textarea> </div> <div> <input type="button" value="提交" class="CommentSub"> </div> </form> {# 富文本編輯框設置#} Keditor = KindEditor.create("#contentArea", { width: "850px", resizeType: 1, uploadJson: "/upload_file/", {# 指定上傳文件的服務器端程序。 #} extraFileUploadParams: {"csrfmiddlewaretoken": "{{ csrf_token }}"}, {# 上傳圖片、Flash、視音頻、文件時,支持添加別的參數一並傳到服務器。 #} filePostName: "imgFile" });
非常有用的取值和賦值操作:


第三點:采用文本編輯框輸入評論內容,用ajax方式提交評論時,要注意運用:$(document).ready(function(){})============>$(function(){})
第四點:處理新添評論時,前端有兩種方式,一種字符串拼接,還有我們可以有效的借助別人寫好的格式化字符串處理工具。
第五點:BeautifulSoup模塊 --針對標簽進行匹配查詢
第六點:文章一載入即顯示樹形評論
##############遞歸函數##############
{# 遞歸函數#}
function makeCommentTree(comment_list) {
var htmls = '';
$.each(comment_list, function (i, comment) {
{# console.log(i, comment);#}
{# var comment_str = '<div class="comment_item"><div class="content"><span>' + comment["id"] + '</span></div>';#}
var comment_str = '<div class="comment_item"><div class="row">' +
'<div class="col-md-1"><a href="#"><img src="' + comment["comment_user_headPic"] + '" width="40px" height="40px" class="comment_user_headPic"></a></div>' +
'<div class="col-md-11"><span class="comment_time">' + comment["create_time"] + '</span>' +
'<a href="#" class="comment_user">' + comment["comment_user_username"] + '</a>' +
'<a href="#contentArea2" class="comment_comment pull-right">回復<span class="glyphicon glyphicon-comment"></span></a>' +
'<a href="#" class="pull-right">支持<span class="glyphicon glyphicon-thumbs-up"></span> </a>' +
'<div class="comment_info">' + comment["commentInfo"] + '</div><span class="' + comment["id"] + '"></span></div></div>';
if (comment["children_comments"]) {
comment_str += makeCommentTree(comment["children_comments"]);
}
comment_str += '</div>';
htmls += comment_str;
});
return htmls;
}
################樣式設置:多級評論顯示出層級效果的關鍵一步:
$(".comment_item").css({"marginLeft": "40px", "marginBottom": "10px"});
tips1:無序字典變有序字典
from collections import OrderDict import collections comment_dict=collections.OrderDict()
tips2:常用
1、window.location.href(設置或獲取整個 URL 為字符串) var test = window.location.href; alert(test); 返回:http://i.cnblogs.com/EditPosts.aspx?opt=1 2、window.location.protocol(設置或獲取 URL 的協議部分) var test = window.location.protocol; alert(test); 返回:http: 3、window.location.host(設置或獲取 URL 的主機部分) var test = window.location.host; alert(test); 返回:i.cnblogs.com 4、window.location.port(設置或獲取與 URL 關聯的端口號碼) var test = window.location.port; alert(test); 返回:空字符(如果采用默認的80端口(update:即使添加了:80),那么返回值並不是默認的80而是空字符) 5、window.location.pathname(設置或獲取與 URL 的路徑部分(就是文件地址)) var test = window.location.pathname; alert(test); 返回:/EditPosts.aspx 6、window.location.search(設置或獲取 href 屬性中跟在問號后面的部分) var test = window.location.search; alert(test); 返回:?opt=1 PS:獲得查詢(參數)部分,除了給動態語言賦值以外,我們同樣可以給靜態頁面,並使用javascript來獲得相信應的參數值。 7、window.location.hash(設置或獲取 href 屬性中在井號“#”后面的分段) var test = window.location.hash; alert(test); 返回:空字符(因為url中沒有) 8、js獲取url中的參數值
暫時就這些。
當然博客系統還有很多未整理出來的,比如用戶注冊時上傳頭像的預覽,涉及的FormData。驗證碼的刷新。對文章按日期歸檔時運用的自定義管理器。
request.path運用(
要求:
1 用戶登陸后才能訪問某些頁面,
2 如果用戶沒有登錄就訪問該頁面的話直接跳到登錄頁面
3 用戶在跳轉的登陸界面中完成登陸后,自動訪問跳轉到之前訪問的地址)
后續補充。
