BBS_02day:

展示个人所有文章:

def article_detail(request,username,article_id):
# 将文章查询出来
article_obj = models.Article.objects.filter(pk=article_id).first()
blog = article_obj.blog
# 还应该获取当前文章所有的评论信息
comment_list = models.Comment.objects.filter(article=article_obj)
if not article_obj: #没有则404
return render(request,'error.html')
return render(request,'article_detail.html',locals())

点赞,点彩功能:

import json
from django.db.models import F
from django.utils.safestring import mark_safe
def updown(request):
if request.is_ajax():
if request.method == 'POST':
back_dic = {'code':1000,'msg':''}
is_up = request.POST.get('is_up') # 是一个字符串格式的json数据
article_id = request.POST.get('article_id')
is_up = json.loads(is_up) # 将json格式的字符串数据转成python对应的数据类型
# print(is_up,type(is_up))
"""
点赞点踩业务逻辑
1.判断当前用户是否登录
2.当前这篇文章是否是当前用户自己写的
3.当前这篇文章用户是否已经点过
4.操作数据库 完成数据修改
1.点赞点踩添加数据的时候
2.文章表里面对应的普通字段也得修改
"""
# 1.判断当前用户是否登录
if request.user.is_authenticated():
# 2.当前这篇文章是否是当前用户自己写的
article_obj = models.Article.objects.filter(pk=article_id).first()
if not article_obj.blog.userinfo == request.user:
# 3.当前这篇文章用户是否已经点过
is_click = models.UpAndDown.objects.filter(user=request.user,article=article_obj).exists()
if not is_click:
# 操作数据库 完成数据修改
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'] = '点踩成功'
models.UpAndDown.objects.create(user=request.user,article=article_obj,is_up=is_up)
else:
back_dic['code'] = 2000
back_dic['msg'] = '你已经点过了不能在点了'
else:
back_dic['code'] = 3000
back_dic['msg'] = '你个臭不要脸的 不能给自己点' else:
back_dic['code'] = 4000
back_dic['msg'] = mark_safe('请先<a href="/login/">登录</a>') #后端直接与前端交互
return JsonResponse(back_dic)

评论功能:

from django.db import transaction

def comment(request):
if request.is_ajax():
if request.method == 'POST':
back_dic = {'code':1000,'msg':''}
article_id = request.POST.get('article_id')
content = request.POST.get('content')
# parent_id如果有值那么正常存储 如果没有值也无所谓就存空 也符合要求
parent_id = request.POST.get('parent_id')
with transaction.atomic():
models.Comment.objects.create(user=request.user,article_id=article_id,content=content,parent_id=parent_id)
models.Article.objects.filter(pk=article_id).update(comment_num = F('comment_num') + 1) #F(): 变量动态值的运算
back_dic['msg'] = '评论成功'
return JsonResponse(back_dic)

页面展示:

#article_detail.html

{% extends 'base.html' %}

{% block css %}
<style>
#div_digg {
float: right;
margin-bottom: 10px;
margin-right: 30px;
font-size: 12px;
width: 128px;
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;
} .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: #808080;
}
</style>
{% endblock %}
{% block content %}
<div>
<h2>{{ article_obj.title }}</h2>
{{ 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">
<span class="info" style="color: red"></span>
</div>
</div>
</div>
{# 点赞点踩样式结束 #} {# 评论楼渲染#}
<div>
<ul class="list-group">
{% for comment in comment_list %}
{# #15楼 2019-11-08 20:03 蔡彦辉的博客#}
<li class="list-group-item">
<span><a href="#">#{{ forloop.counter }}楼</a></span>
<span>{{ comment.create_time|date:'Y-m-d' }}</span>
<span><a href="/{{ comment.user.username }}/">{{ comment.user.username }}</a></span>
<span><a class="reply pull-right" username="{{ comment.user.username }}" comment_id="{{ comment.pk }}">回复</a></span>
<div>
{% if comment.parent %}
<p>@{{ comment.parent.user.username }}</p>
{% endif %}
{{ comment.content }}
</div>
</li>
{% endfor %}
</ul>
</div> {# 评论开始#}
{% if request.user.is_authenticated %}
<div>
<p>发表评论</p>
<p>
昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50"
value="{{ request.user.username }}">
</p>
<p>评论内容:</p>
<p>
<textarea name="comment" id="id_comment" cols="60" rows="10"></textarea>
</p>
<button class="btn btn-primary" id="id_submit">提交评论</button>
</div>
{% else %}
<p><a href="{% url 'login' %}">登录</a>&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{% url 'register' %}">注册</a></p> {% endif %} {# 评论结束#} </div> <script>
// 点赞点踩
$('.action').click(function () {
let isUp = $(this).hasClass('diggit');
let $target = $(this);
$.ajax({
url: '/up_down/',
type: 'post',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'is_up': isUp,
'article_id': "{{ article_obj.pk }}"
},
success: function (data) {
if (data.code == 1000) {
// 给span标签渲染信息
$('.info').text(data.msg);
// 点赞或点踩成功之后 应该将前端的数字也加一
let $span = $target.children();
let oldNum = $span.text();
$span.text(Number(oldNum) + 1) // 转整型相加 不然就是字符串拼接了
} else {
$('.info').text(data.msg)
}
}
})
});
// 评论
// 提前定义一个全局变量parentId
let parentId = null;
$('#id_submit').click(function () {
// 判断全局的parentid是否有值 如果有 你应该将前面的@人名\n切除
let content = $('#id_comment').val();
if (parentId){
// 获取\n所在的索引值
let nIndex = content.indexOf('\n') + 1; // 索引顾头不顾尾 加一才能切到
// 按照nIndex切换文本内容
content = content.slice(nIndex) // 将nIndex之前的内容直接去除 保留之后的内容 } $.ajax({
url: '/comment/',
type: 'post',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'content':content,
'article_id': '{{ article_obj.pk }}',
'parent_id':parentId
},
success: function (data) {
if (data.code == 1000){
// 临时渲染
let userName = '{{ request.user.username }}';
let content = $('#id_comment').val();
let tmp = `
<li class="list-group-item">
<span><span class="glyphicon glyphicon-comment"></span><a href="/${ userName}/">${userName}:</a></span>
<p>
${content}
</p>
</li> `;
// 将生成好的内容添加到ul标签内部
$('.list-group').append(tmp);
// 将评论框中的内容清空
$("#id_comment").val('');
// 将全局的parentid再制成空null
parentId = null;
}
}
})
});
// 点击回复按钮
$('.reply').on('click',function () {
// 如何获取想要评论的那条评论人的姓名
let userName = $(this).attr('username');
// 如何获取要评论的那条评论的主键值
parentId = $(this).attr('comment_id'); // 赋值给全局的parentId
// 回复按钮的三件事
let headerMsg = '@' + userName + '\n';
$('#id_comment').val(headerMsg);
$('#id_comment').focus(); // 让评论框自动聚焦 })
</script>
{% endblock %}

BBS_02day的更多相关文章

随机推荐

  1. linux 用du查看硬盘信息

    linux 用du查看硬盘信息 <pre>[root@iZ238qupob7Z web]# df -hFilesystem Size Used Avail Use% Mounted on/ ...

  2. 最锋利的Visual Studio Web开发工具扩展:Web Essentials详解【转】

    Web Essentials是目前为止见过的最好用的VS扩展工具了,具体功能请待我一一道来. 首先,从Extension Manager里安装:最新版本是19号发布的2.5版 然后重启你的VS开发环境 ...

  3. 基于SqlClient开发SQLServer工具类 伸手党的福音

    注意:代码直接Copy调用即可,SQLServer工具类跟我上一个Oracle工具类有所不同,区别在于调用存储过程中时参数的使用,无需输入对应的存储游标名称 特点:根据用户传入的参数类型来识别存储中对 ...

  4. C#中使用WCF创建面向网络的服务程序

    如题. 这种东西基于微软的一整套东西,在.NET内使用特别方便.利弊自行衡量,是否使用自行决定. 步骤1.创建一组在网上发布的方法 新建项目,类型选择“WCF服务应用程序”  在项目里,你可以补充任意 ...

  5. webpack中使用DefinePlugin来传递构建的环境变量给源代码使用

    最近在思考如何提供一种前后端开发功能测试既高效又安全的方案,因为对于我平时的项目是前后端同时进行的,后端我已经有了完备的权限管理,前端不能的角色会有不同的访问数据权限.而在vue前后端分离开发情况下, ...

  6. java9模块不可见问题

    问题描述 jdk.internal.reflect包不可见 问题原因 java9模块化之后,java.base只把jdk.internal.reflect暴露给了少数几个内部包而没有向当前模块暴露. ...

  7. 高强度学习训练第四天总结:JVM+Redis

    JVM 复习了JVM堆内存的几个模块. 复习了JVM的几个控制工具. 复习了JVM发展历史 Redis 复习了Redis的事务控制.

  8. E203 译码模块(2)

    常用的alu算术运算指令(包括ecall和 ebreak)在regular alu单元处理.regular alu单元为alu单元的一个子单元.regular单元的信息总线共21位,格式如下图所示,其 ...

  9. getopt、getopt_long命令参数

    参数 optstring为选项字符串.如果选项字符串里的字母后接着冒号":",则表示还有相关的参数 getopt int getopt(int argc, char * const ...

  10. Vue实战狗尾草博客管理系统第一章

    Vue实战狗尾草博客后台管理系统第一章 这里准备采用的技术栈为:vue全家桶+element-ui 这里因为是后台管理系统,没有做SSR的必要.所以这里就采用前后端分离来昨晚这个项目~ 项目搭建 vu ...