由於做博客園系統的時候發現評論功能的實現耗費蠻長時間,比較適合練習,遂整理如下:
評論分為:對文章的評論和對評論的評論。
有兩種方式實現多級評論,一種類似博客園特色的評論方式,蓋樓@某位用戶。一種采用樹形結構實現,涉及一個很重要的點:字典和列表是引用數據類型,或者說可變類型;字典的鍵必須是不可變類型(可以是整型)。
主要整理第二種,學習數據結構的設計思想:
評論結構:
數字代表評論的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 用戶在跳轉的登陸界面中完成登陸后,自動訪問跳轉到之前訪問的地址)
后續補充。