Blog Systerm--多级评论的树形结构实现方式


由于做博客园系统的时候发现评论功能的实现耗费蛮长时间,比较适合练习,遂整理如下:

评论分为:对文章的评论和对评论的评论。

有两种方式实现多级评论,一种类似博客园特色的评论方式,盖楼@某位用户。一种采用树形结构实现,涉及一个很重要的点:字典和列表是引用数据类型,或者说可变类型;字典的键必须是不可变类型(可以是整型)。

主要整理第二种,学习数据结构的设计思想:

评论结构:

数字代表评论的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  用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址)

后续补充。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM