一、文章评论功能实现流程
文章评论包含两种评论,根评论:对文章的评论;子评论:对评论的评论。两者的区别在于是否存在父评论。
实现流程:1、构建样式;2、提交根评论;3、显示根评论(分为render显示和Ajax显示);4、提交子评论;5、显示子评论(分为render显示和Ajax显示);6、评论树显示(博客园是楼层显示)。
二、构建评论样式
1、article_detail.html:
{# 文章点赞,清除浮动 #}
<div class="clearfix">
<div id="div_digg">
{# 推荐 #}
<div class="diggit action">
<span class="diggnum" id="digg_count">{
{ article_obj.up_count }}</span>
</div>
{# 点灭 #}
<div class="buryit action">
<span class="diggnum" id="bury_count">{
{ article_obj.down_count }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips" style="color: red;"></div>
</div>
</div>
<div class="comments">
<p>发表评论</p>
<p>昵称: <input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50" value="{
{ request.user.username }}"></p>
<p>评论内容</p>
<textarea name="" id="" cols="60" rows="10"></textarea> {# textarea是一个内联标签 #}
<p><button class="btn btn-default comment_btn">提交评论</button></p>
</div>
由于id=div_digg中存在浮动,显示时会造成点赞区域和评论区域在同一行,在点赞区外包了一层div标签,添加bootstrap的clearfix清除浮动。
由于textarea是一个内联标签,下面直接接button标签,文本框和按钮会显示在同一行,同样给按钮包一层p标签,让按钮在文本框下方显示。
2、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;
}
3、显示效果如下所示:
三、提交根评论
1、创建评论路由
urlpatterns = [
...
path('digg/', views.digg), # 点赞
path('comment/', views.comment), # 评论
...
]
2、创建评论视图函数comment
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)
return HttpResponse("comment")
3、在article_detail.html模板中创建评论事件
<script>
// 点赞请求
$('#div_digg .action').click(function () {
...
// 评论请求
$(".comment_btn").click(function () {
var content = $('#comment_content').val(); // 拿到评论框的内容
var pid = ""; // 父评论默认为空
$.ajax({
url: "/comment/",
type: "post",
data: {
'csrfmiddlewaretoken': $("[name= 'csrfmiddlewaretoken']").val(),
'article_id': "{
{ article_obj.pk }}",
'content': content,
'pid': pid,
},
success:function (data) {
console.log(data);
// 提交后清空评论框
$("#comment_content").val("");
}
})
})
</script>
4、提交评论后,在数据库blog_comment表中可以看到评论记录
四、显示根评论
1、render显示根评论
(1)要render显示评论,需要修改article_detail视图函数
def article_detail(request, username, article_id):
user = UserInfo.objects.filter(username=username).first()
blog = user.blog
article_obj = models.Article.objects.filter(pk=article_id).first()
comment_list = models.Comment.objects.filter(article_id=article_id)
return render(request, "article_detail.html", locals())
传递comment_list到模板中,根据过滤条件获取的是当前文章的评论。
(2)在article_detail.html中构建评论列表
{# 文章评论列表 #}
<div class="comments">
<p>评论列表</p>
<ul class="list-group comment_list">
{% for comment in comment_list %}
<li class="list-group-item">
<div>
<a href=""># {
{ forloop.counter }}楼</a>
<span>{
{ comment.create_time|date:"Y-m-d H:i" }}</span>
<a href=""><span><{
{ comment.user.username }}/span></a>
<a href="" class="pull-right">回复</a>
</div>
<div class="comment_con">
{# 评论内容 #}
<p>{
{ comment.content }}</p>
</div>
</li>
{% endfor %}
</ul>
<p>发表评论</p>
<p>昵称: <input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50" value="{
{ request.user.username }}"></p>
<p>评论内容</p>
<textarea name="" id="comment_content" cols="60" rows="10"></textarea> {# textarea是一个内联标签 #}
<p><button class="btn btn-default comment_btn">提交评论</button></p>
</div>
1)利用bootstrap的列表组组件来构建文章列表样式。
2)修饰评论内容样式article_detail.css:
.comment_con {
margin-top: 10px;
}
(3)显示效果
2、Ajax显示根评论
(1)更新comment视图函数,准备返回给ajax回调函数处理的数据
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 = {}
# create_time是一个datetime.datetime对象,在json序列化时不能对对象进行json序列化,必须进行strftime的转换
response["create_time"] = comment_obj.create_time.strftime("%Y-%m-%d %X")
# 评论人
response["username"] = request.user.username
# 内容
response["content"] = content
return JsonResponse(response)
(2)回调函数处理数据,显示新的评论
// 评论请求
$(".comment_btn").click(function () {
var content = $('#comment_content').val(); // 拿到评论框的内容
var pid = ""; // 父评论默认为空
$.ajax({
url: "/comment/",
type: "post",
data: {
'csrfmiddlewaretoken': $("[name= 'csrfmiddlewaretoken']").val(),
'article_id': "{
{ article_obj.pk }}",
'content': content,
'pid': pid,
},
success: function (data) {
console.log(data);
// 获取