7.博客系统

7.博客系统

根评论:对文章的评论;

子评论:对评论的评论;

区别:是否有父评论。

评论的流程:

1构建样式

2提交根评论

3显示根评论

--------render显示

--------Ajax显示

4提交子评论

5显示子评论

--------render显示

--------Ajax显示

6评论树的显示

楼层结构:

111

222

333

树形结构:(有父子关系,楼层的深度、层级)

111

222

444

555

333

1.评论样式

article_detail.html

//评论和点赞在一行,这是由于点赞和反对做了一个浮动,而评论又在正常文档中,导致它的浮动没有清除;清除浮动在bootstrap里边加个clearfix
{# 评论样式#}

发表评论

昵称:

评论内容:

//没有必要放到form表单中,因为要Ajax提交;textarea为内联标签,给下面button加了个p标签。

//

article_detail.css

input.author{

background-image: url("/static/font/icon_form.gif"); //引入图标

background-repeat: no-repeat;

border: 1px solid #ccc;

padding: 4px 4px 4px 30px;

width: 300px;

font-size: 13px;

background-position: 3px -3px;

}

2.提交(保存)根评论

客户端浏览器发 点赞或者评论按钮给服务端,触发一个事件(给它绑定一个click事件)发送请求,用户一点击就给服务器发请求了,有专门的视图函数接收这个请求,提交评论信息交给comment视图函数,视图函数构建一个评论对象保存到数据库里边,然后再把响应交给回调函数(ajax发完请求给它个回调) ,通过响应结果来判断如果对这个dom操作

views.py

#评论

def comment(request):

print(request.POST)

article_id = request.POST.get("article_id") #评论文章;user不用传,create_time不用传(评论的时间就是入库的时间),评论表的字段。

pid = request.POST.get("pid")

content = request.POST.get("content") #评论内容

user_id = request.user.pk #当前登录人的id

comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,parent_comment_id=pid) //pid是为空的,传给父评论

return HttpResponse("comment")

article_detail.html

//评论请求

$(".commment_btn").click(function () {

var pid = ""

var content = $("#comment_content").val(); //找到这个标签,val就是取里边的内容

$.ajax({

url:"/comment/",

type:"post",

data:{

"csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val(),

"article_id":"{{ article_obj.pk }}",

"content":content,

"pid":pid //父评论的id,默认为空。根评论没有

},

success: function (data) { //success回调函数

console.log(data)

//清空评论框

$("#comment_content").val("");

}

})

})

3.render显示根评论(还有一种是Ajax)

views.py

def article_detail(request, username, article_id):

'''

文章详情页

:param request:

:param username:

:param article_id:

:return:

'''

user = models.UserInfo.objects.filter(username=username).first() #个人站点对象

blog = user.blog

article_obj = models.Article.objects.filter(pk=article_id).first() #拿到文章对象,要传到模板里边去

# context = get_classification_data(username)

comment_list = models.Comment.objects.filter(article_id=article_id) #拿出用户访问那篇文章的id

return render(request, "article_detail.html", locals())

article_detail.html

评论列表

Ajax显示评论

点提交按钮,发Ajax请求;

Ajax请求在对应的视图函数生成一个comment对象,然后我们响应给它的是comment对象相关的三个键值字典,字典返回给这个回调函数,拿到object对象构建一个标签,把标签字符串样式放在了页面的某个url里边去了完成了dom操作。

success: function (data) {

console.log(data);

var create_time = data.create_time; //取出这三组变量,把这三个变量插入到下面反引号里边,关于js必须用+不断的去拼接,现在用ES6反引号的语句就很简洁了

var username = data.username;

var content = data.content;

var s =` //反斜杠 ;构建一个标签字符串像上边那样放到这个样式里边 ;通过dom操作放到这个url中

  • ${create_time}/span> //用反引号把字符串包起来,再用${}语法把它插入进来,js里边的只能用+拼,ES6很像python的语法

    ${ username }

    ${content}

  • `;

    $("ul.comment_list").append(s);

    views.py

    #评论

    def comment(request):

    print(request.POST)

    article_id = request.POST.get("article_id")

    pid = request.POST.get("pid")

    content = request.POST.get("content")

    user_id = request.user.pk

    comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,parent_comment_id=pid)

    response = {} #这个就是返回给回调函数的那个data。

    response["create_time"] = comment_obj.create_time.strftime("%Y-%m-%d %X")

    response["username"] = request.user.username #当前评论人

    response["content"] = content

    return JsonResponse(response) #返回一个字典,JsonResponse会帮我们做序列化操作;

    #return HttpResponse("comment")

    先点提交按钮发ajax请求,在对应的视图函数中生成一个对象,响应给它的是comment相关信息-三个键值组成的字典,把字典返回给success回调函数,success拿到那个字典 拿到object对象,构建一个标签,把标签字符串放到页面的某个ul里边去了,完成一个dom操作。(在数据库里边生成一个comment记录,同时在页面上看到提交的这条评论信息了)

    4. 回复按钮事件

    一点击回复按钮,就@这条评论的评论人; 定光标、赋文本值。

    #{{ forloop.counter }}楼   

    {{ comment.create_time | date:"Y-m-d H:i" }}   

    {{ comment.user.username }}

    回复

    //回复按钮事件

    $(".reply_btn").click(function () {

    $('#comment_content').focus(); //聚焦

    var val="@"+$(this).attr("username")+"\n"; //赋值,父评论的名字

    $('#comment_content').val(val)

    })

    5.提交子评论

    #{{ forloop.counter }}楼   

    {{ comment.create_time | date:"Y-m-d H:i" }}   

    {{ comment.user.username }}

    回复 //给每个回复的按钮多加一个自定义的属性

    //评论请求

    var pid = "";

    $(".commment_btn").click(function () {

    var content = $("#comment_content").val(); //把评论内容取出来

    if(pid){ //判断pid是否为空。

    var index=content.indexOf("\n")

    content = content.slice(index+1)

    }

    //清空评论框

    pid = "", //加上它可以清除小bug(你不刷新时,不点击回复按钮之间输入pid则为子评论)

    $("#comment_content").val("");

    //回复按钮事件

    $(".reply_btn").click(function () {

    $('#comment_content').focus();

    var val="@"+$(this).attr("username")+"\n";

    $('#comment_content').val(val);

    pid = $(this).attr("comment_pk")

    })

    6.Ajax显示子评论

    应该重新构建标签字符串,从视图中拿到父评论的相关信息,加到s字符串里边

    7.评论树的显示

    权限展示成树形结构,用递归

    评论树的请求数据

    评论树

    {#

    #}

    {# 111#}

    {#

    #}

    {# 444#}

    {#

    #}

    {# 555#}

    {#

    #}

    {#

    #}

    {#

    #}

    {#

    #}

    {# 222#}

    {#

    #}

    {#

    #}

    {# 333#}

    {#

    #}

    views.py

    def get_comment_tree(request):

    article_id = request.GET.get("article_id")

    ret = list(models.Comment.objects.filter(article_id=article_id).values("pk", "content", "parent_comment_id"))

    return JsonResponse(ret, safe=False)

    根评论的序号一定大于子评论的序号

    ret = list(models.Comment.objects.filter(article_id=article_id).order_by("pk").values("pk", "content", "parent_comment_id"))

    return JsonResponse(ret, safe=False)

    评论事务操作

    from django.db import transaction#事务操作

    with transaction.atomic():

    comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,parent_comment_id=pid)

    models.Article.objects.filter(pk=article_id).update(comment_count=F("comment_count")+1)

    评论的邮件发送

    EMAIL_HOST = 'smtp.exmail.qq.com' #如果是163改成 smtp.163.com

    EMAIL_POST = 465

    EMAIL_HOST_USER = ' ' #账号

    EMAIL_HOST_PASSWORD = ' ' #密码

    #DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

    EMAIL_USE_SSL = True

    TRANSLATE with x

    English

    Arabic

    Hebrew

    Polish

    Bulgarian

    Hindi

    Portuguese

    Catalan

    Hmong Daw

    Romanian

    Chinese Simplified

    Hungarian

    Russian

    Chinese Traditional

    Indonesian

    Slovak

    Czech

    Italian

    Slovenian

    Danish

    Japanese

    Spanish

    Dutch

    Klingon

    Swedish

    English

    Korean

    Thai

    Estonian

    Latvian

    Turkish

    Finnish

    Lithuanian

    Ukrainian

    French

    Malay

    Urdu

    German

    Maltese

    Vietnamese

    Greek

    Norwegian

    Welsh

    Haitian Creole

    Persian

    TRANSLATE with

    COPY THE URL BELOW

    Back

    EMBED THE SNIPPET BELOW IN YOUR SITE

    Enable collaborative features and customize widget: Bing Webmaster Portal

    Back

    此页面的语言为中文(简体)

    翻译为

    中文(简体)

    中文(繁体)

    丹麦语

    乌克兰语

    乌尔都语

    亚美尼亚语

    俄语

    保加利亚语

    克罗地亚语

    冰岛语

    加泰罗尼亚语

    匈牙利语

    卡纳达语

    印地语

    印尼语

    古吉拉特语

    哈萨克语

    土耳其语

    威尔士语

    孟加拉语

    尼泊尔语

    布尔语(南非荷兰语)

    希伯来语

    希腊语

    库尔德语

    德语

    意大利语

    拉脱维亚语

    挪威语

    捷克语

    斯洛伐克语

    斯洛文尼亚语

    旁遮普语

    日语

    普什图语

    毛利语

    法语

    波兰语

    波斯语

    泰卢固语

    泰米尔语

    泰语

    海地克里奥尔语

    爱沙尼亚语

    瑞典语

    立陶宛语

    缅甸语

    罗马尼亚语

    老挝语

    芬兰语

    英语

    荷兰语

    萨摩亚语

    葡萄牙语

    西班牙语

    越南语

    阿塞拜疆语

    阿姆哈拉语

    阿尔巴尼亚语

    阿拉伯语

    韩语

    马尔加什语

    马拉地语

    马拉雅拉姆语

    马来语

    马耳他语

    高棉语

    随时将中文(简体)翻译为PRO 一律不翻译中文(简体) 一律不翻译i.cnblogs.com

    相关推荐

    怎么调节鼠标的灵敏度
    365bet开户

    怎么调节鼠标的灵敏度

    📅 02-02 👁️ 7977
    firefox临时文件位置及修改方法
    365bet网上足球比赛

    firefox临时文件位置及修改方法

    📅 10-20 👁️ 327