六、文章详情、点赞、评论

文章详情页面:

def article_detail(request, username, article_id):
# user_obj = models.UserInfo.objects.filter(username=username)
article_obj = models.Article.objects.filter(pk=article_id).first()
blog = models.Blog.objects.filter(userinfo__username=username).first()
comment_list = models.Comment.objects.filter(article_id=article_id)
return render(request, 'article_detail.html', locals())

views.py 文章详情页

{% extends 'base.html' %}

{% block css %}
<style>
#div_digg {
float: right;
margin-bottom: 10px;
margin-right: 30px;
font-size: 12px;
width: 125px;
text-align: center;
margin-top: 10px;
} .diggit {
float: left;
width: 46px;
height: 52px;
background: url('/static/img/upup.gif') no-repeat;
text-align: center;
cursor: pointer;
margin-top: 2px;
padding-top: 5px;
} #div_digg .diggnum {
line-height: 1.5em !important;
} .diggnum {
font-size: 14px;
color: #075db3;
font-family: Verdana;
} .buryit {
float: right;
margin-left: 20px;
width: 46px;
height: 52px;
background: url("/static/img/downdown.gif") no-repeat;
text-align: center;
cursor: pointer;
margin-top: 2px;
padding-top: 5px;
} .clear {
clear: both;
} .diggword {
margin-top: 5px;
margin-left: 0;
font-size: 12px;
color: gray;
}
</style>
{% endblock %}
{% block content %}
{# <h3>{{ article_obj.title }}</h3>#}
{{ article_obj.content|safe }}
<div class="clearfix"> <div id="div_digg">
<div class="diggit action">
<span class="diggnum" id="digg_count">{{ article_obj.up_num }}</span>
</div>
<div class="buryit action">
<span class="burynum" id="bury_count">{{ article_obj.down_num }}</span>
</div>
<div class="clear"></div>
<div class="diggword" id="digg_tips" style="color: red;"></div>
</div>
</div>
<hr>
{# --------------------评论内容部分 开始 ------------------- #}
<p>评论列表:</p>
<div class="form-group list-group">
{% for comment in comment_list %} <div class="form-group"><span style="color: cornflowerblue">#{{ forloop.counter }}楼&nbsp;</span>
{{ comment.create_time|date:'Y-m-d' }}&nbsp;
<a href="/{{ comment.user.username }}/">{{ comment.user.username }}</a>
<span class="pull-right reply" comment_id="{{ comment.pk }}" username={{ comment.user.username }}><a>回复</a></span>
<div>
{% if comment.parent %}
<p>@&nbsp;{{ comment.parent.user.username }}</p>
{% endif %}
<p style="color: darkgray">&nbsp;&nbsp;{{ comment.content }}</p>
<hr>
</div>
</div>
{% endfor %} </div>
{# --------------------评论内容部分 结束 ------------------- #}
{% if request.user.is_authenticated %}
{# -----------------------------评论部分 开始 ---------------------- #}
<div>
<p><span class="glyphicon glyphicon-comment"></span>发表评论</p>
<p>
<span>昵称:<span class="glyphicon glyphicon-user"></span></span>
<input type="text" value="{{ request.user.username }}" disabled>
</p>
<p>评论内容:</p>
<textarea name="" cols="80" rows="10" id="id_comment"></textarea>
<p>
<button class="btn btn-primary" id="id_submit">提交评论</button>
</p>
<br><br><br>
</div>
{# ------------------------------评论部分 结束 ---------------------- #}
{% endif %}
{% endblock %} {% block js %}
<script>
console.log("this is script!");
// 点赞点踩
$('.action').click(function () {
{#alert($(this).hasClass('diggit')) 利用类操作判断是否有某一个类属性从而区分是点赞还是点踩#}
let isUp = $(this).hasClass('diggit');
let $info = $('#digg_tips');
let $span = $(this).children();
$.ajax({
url: "/up_or_down/",
type: 'post',
data: {
'article_id':{{ article_obj.pk }},
'is_up': isUp,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function (data) {
if (data.code == 200) {
$info.html(data.msg);
// 将span标签内部的文本数字加1
$span.text(Number($span.text()) + 1)
} else {
$info.html(data.msg)
}
}
})
}); let parentId = '';
// 提交评论
$('#id_submit').click(function () {
console.log("this is 提交数据!");
let sub_content = $('#id_comment').val();
if (sub_content == ''){
alert("评论不能为空!")
}else{
console.log('this is sub_content:', sub_content);
if (parentId){
let indexVal = sub_content.indexOf('\n') +1;
sub_content = sub_content.slice(indexVal);
console.log(sub_content)
}
// 分析: 将评论提交到后端,需要传 文章id、评论内容,评论人的id
$.ajax({
url: '/comment/',
type: 'post',
data: {
'article_id': '{{ article_id }}',
'content': sub_content,
'csrfmiddlewaretoken': '{{ csrf_token }}',
'parentId': parentId, },
success: function (data) {
if (data.code == 100) {
let userName = '{{ request.user.username }}';
let content = sub_content;
let tempStr = `
<div>
<p class="form-group"><span style="color: cornflowerblue">
<a href="/${userName}/">${userName}</a>
</p>
<p style="color: darkgray">&nbsp;&nbsp;${content}</p>
<hr>
</div>
`;
$(".list-group").append(tempStr);
// 将textarea框中的内容清空
$('#id_comment').val('');
// 将全局的parentId清空
parentId = ''
}
}
}) }
}); // 回复按钮逻辑代码
$('.reply').click(function () {
// 1.把你想评论的那条评论所属者的名字添加到textarea中(@+用户名) 如何获取评论人名
let pUserName = $(this).attr('username');
let pCommentId = $(this).attr('comment_id');
// 2.自动换行
$('#id_comment').val('@'+pUserName+'\n');
// 3.textarea自动聚焦
$('#id_comment').focus();
// 4.将全局的parentId赋值
parentId = pCommentId;
});
</script>
{% endblock %}

article_detail.html

def up_or_down(request):
back_dic = {'code': 100, 'msg': ''}
if request.is_ajax():
is_up = request.POST.get('is_up')
is_up = json.loads(is_up) # 利用json模块反序列称后端python布尔值类型
article_id = request.POST.get('article_id') # 1.判断用户是否登录
if request.user.is_authenticated():
# 2.判断文章是否是当前用户写的
article_obj = models.Article.objects.filter(pk=article_id).first()
if not article_obj.blog.userinfo.pk == request.user.id:
# 3.判断当前用户是否对该文章点赞或点踩了
res = models.UpAndDown.objects.filter(user=request.user, article=article_obj)
if not res:
# 4.需要在两张表里面修改数据
# 先修改普通字段的数据
if is_up:
# 点赞
models.Article.objects.filter(pk=article_id).update(up_num=F('up_num') + 1)
back_dic['msg'] = '点赞成功'
else:
# 点踩
models.Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1)
back_dic['msg'] = '点踩成功'
# 最后修改UpAndDown表数据
models.UpAndDown.objects.create(user=request.user, article=article_obj, is_up=is_up)
back_dic['code'] = 200
else:
back_dic['code'] = 201
back_dic['msg'] = '你已经点过了'
else:
back_dic['code'] = 202
back_dic['msg'] = '你个臭不要脸的不能点自己的'
else:
back_dic['code'] = 203
back_dic['msg'] = mark_safe('请先<a href="/login/">登录</a>')
return JsonResponse(back_dic)

views.py 点赞点踩

def comment(request):
back_dic = {'code': 100, 'msg': ''}
if request.is_ajax():
# 获取前端发过来的数据
# print("this is comment!")
article_id = request.POST.get('article_id')
# print(article_id)
content = request.POST.get('content')
# print(content)
parent_id = request.POST.get('parentId')
# print(parent_id)
if request.user.is_authenticated():
# print("已经登录,正要去写评论入库")
with transaction.atomic():
# 在文章表中普通的评论字段加1
models.Article.objects.filter(pk=article_id).update(comment_num=F('comment_num') + 1)
# 再在评论表中将评论的信息存储
models.Comment.objects.create(user=request.user, article_id=article_id, content=content,
parent_id=parent_id)
back_dic['msg'] = '评论成功!'
else:
back_dic['code'] = 101
back_dic['msg'] = '请想登录!'
return JsonResponse(back_dic)

views.py 评论

BBS论坛 文章详情、点赞、评论的更多相关文章

  1. BBS之文章详情页搭建

    博客评论相关 博客文章详情页搭建 {% extends 'base.html' %} {% block css %} <style> #div_digg { float: right; m ...

  2. Django:文章详情页面评论功能需要登录后才能使用,登录后自动返回到文章详情页

    背景: 文章详情页正在查看文章,想评论一下写的不错,但是需要先登录才能.页面长这个样子: 方案: 1.点击登录链接时,将该页面的URL传递到登录视图中 request.path获取的是当前页面的相对路 ...

  3. $Django 站点:样式--文章--分类文章--文章详情--文章评论点赞--文章评论点赞统计(数据库优化)

    <h3>个人站点下的</h3> 知识点 url (r'(?P<username>\w+)/p/(?P<id>\d+)', xiangxi,name='x ...

  4. BBS项目分布搭建三(个人站点时间归档补充,实现侧边栏跳转、无线级分类、实现文章详情页展示功能)

    BBS项目分布搭建三(个人站点时间归档补充,) 1. 个人站点时间归档 """ settings.py设置最好更改以下: LANGUAGE_CODE = 'zh-hans ...

  5. Python之路【第十八篇】Django小项目简单BBS论坛部分内容知识点

    开发一个简单的BBS论坛 项目需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可被 ...

  6. python 学习笔记二十 django项目bbs论坛

    项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...

  7. python第一百三十天 ---简单的BBS论坛

    简单的BBS论坛 实现功能 git仓库地址:https://github.com/uge3/BBS 1.整体参考“抽屉新热榜” + “博客园” 2.实现不同论坛版块 3.帖子列表展示 4.个人博客主页 ...

  8. Django小项目简单BBS论坛

    开发一个简单的BBS论坛 项目需求: 1 整体参考"抽屉新热榜" + "虎嗅网" 2 实现不同论坛版块 3 帖子列表展示 4 帖子评论数.点赞数展示 5 在线用 ...

  9. Python开发一个简单的BBS论坛

    项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...

随机推荐

  1. 38-python基础-python3-检查字典中是否存在键或值

    in 和 not in 操作符   请注意, 在前面的例子中,‘name’ in spam 本质上是一个简写版本.相当于'name' in spam.keys()

  2. CentOS6.5下面OpenSSH低版本升级至7.3

    升级前版本: openssl-1.0.1e-48.el6_8.1.x86_64 openssh-5.3p1-118.1.el6_8.x86_64 升级后版本: OpenSSL 1.0.2j OpenS ...

  3. BUUCTF RE部分题目wp

    RE 1,easyre拖进ida,得到flag 2,helloworld 将文件拖入apk改之理,得到flag 3,xor拖进ida,就是简单异或,写脚本 glo=[0x66,0x0a,0x6b,0x ...

  4. 2018-8-10-win10-UWP-button

    title author date CreateTime categories win10 UWP button lindexi 2018-08-10 19:16:53 +0800 2018-2-13 ...

  5. slect fd_set

    select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄(不管是socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工 ...

  6. TCP 三次握手和四次挥手中的ACK 为什么总是SYN + 1 或者 FIN +1 而不是+ 其他数值?

    TCP 三次握手的时候 1.客户端 向服务端发起连接请求,这个时候客户端将发送一个SYN分节(假设其值为J),它告诉服务端我发送数据的初始序列号将是J. 2.服务端收到这个请求后,必须确认(ACK) ...

  7. 【Luogu】【关卡1-8】BOSS战-入门综合练习2(2017年10月)【AK】------都是基础题

    P1426 小鱼会有危险吗 我个人觉得这个题目出的不好,没说明白,就先只粘贴的AC代码吧 #include <bits/stdc++.h> using namespace std; int ...

  8. CSP 2019 模板整合

    qwq以下都为9.24后写的模板 namespace IO{ const int S = 1 << 20; char I[S + 1], *Is = I, *It = I, O[S + 1 ...

  9. 决策树(Decision Tree)算法 python简单实现

    "" """ import numpy as np from math import log import operator import json ...

  10. Django 自定义 admin

    为 model 自定义显示 label是这个Field如果在form中的话会显示的.而verbose_name在form中不会显示.只是作为一种说明而已 callable()   -->  是否 ...