文章详情页点赞点踩评论
展示文章内容
添加文章详情路由
urlpatterns = [ # 文章详情页 path(‘<str:username>/article/<int:article_id>/‘, views.article_detail), # 点赞点踩 path(‘up_or_down/‘, views.up_or_down), # 评论处理 path(‘comment/‘, views.comment), ]
文章详情页视图
def article_detail(request, username, article_id): """ 优先校验username、article_id是否存在 """ user_obj = models.UserInfo.objects.filter(username=username).first() blog = user_obj.blog # 先获取文章对象 article_obj = models.Article.objects.filter(id=article_id, blog__userinfo__username=username).first() if not article_obj: return render(request, ‘errors.html‘) # 获取当前文章的所有评论内容 comment_list = models.Comment.objects.filter(article=article_obj) return render(request, ‘article_detail.html‘, locals())
点赞点踩视图
import json from django.db.models import F def up_or_down(request): """ 校验用户是否登录 自己不能点赞自己的文章 用户是否已点赞当前文章 操作数据库 """ if request.is_ajax(): back_dic = {‘code‘: 1000, ‘msg‘: ‘‘} # 当前用户是否登录 if request.user.is_authenticated: article_id = request.POST.get(‘article_id‘) is_up = request.POST.get(‘is_up‘) # print(is_up, type(is_up)) # true <class ‘str‘> is_up = json.loads(is_up) # print(is_up, type(is_up)) # True <class ‘bool‘> # 当前文章是否是当前用户自己写的 article_obj = models.Article.objects.filter(id=article_id).first() if not article_obj.blog.userinfo == request.user: # 校验当前用户是否已经点了 is_click = models.UpAndDown.objects.filter(user=request.user.username, article=article_obj) if not is_click: # 操作数据库 记录数据 要同步操作普通字段 # 判断当前用户点了赞还是踩 if is_up: # 给点赞数加一 models.Article.objects.filter(id=article_id).update(up_num=F(‘up_num‘) + 1) back_dic[‘msg‘] = ‘点赞成功‘ else: # 给点踩数加一 models.Article.objects.filter(id=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‘] = 1001 back_dic[‘msg‘] = ‘已经点过了‘ else: back_dic[‘code‘] = 1002 back_dic[‘msg‘] = ‘给自己点呀?臭不要脸‘ else: back_dic[‘code‘] = 1003 back_dic[‘msg‘] = ‘请先<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‘: ""} if request.user.is_authenticated: article_id = request.POST.get(‘article_id‘) content = request.POST.get(‘content‘) parent_id = request.POST.get(‘parent_id‘) # print(article_id,content, request.user) # 直接操作两张表存储数据 with transaction.atomic(): models.Article.objects.filter(id=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‘] = 1001 back_dic[‘msg‘] = ‘用户未登录‘ return JsonResponse(back_dic)
文章详情页html
1 {% extends ‘base.html‘ %} 2 3 {% block css %} 4 <style> 5 #div_digg { 6 float: right; 7 margin-bottom: 10px; 8 margin-right: 30px; 9 font-size: 12px; 10 width: 125px; 11 text-align: center; 12 margin-top: 10px; 13 } 14 15 .diggit { 16 float: left; 17 width: 46px; 18 height: 52px; 19 background: url(‘//static.cnblogs.com/images/upup.gif‘) no-repeat; 20 text-align: center; 21 cursor: pointer; 22 margin-top: 2px; 23 padding-top: 5px; 24 } 25 26 .buryit { 27 float: right; 28 margin-left: 20px; 29 width: 46px; 30 height: 52px; 31 background: url(‘//static.cnblogs.com/images/downdown.gif‘) no-repeat; 32 text-align: center; 33 cursor: pointer; 34 margin-top: 2px; 35 padding-top: 5px; 36 } 37 38 .clear { 39 clear: both; 40 } 41 </style> 42 {% endblock %} 43 44 45 {% block content %} 46 <h1>{{ article_obj.title }}</h1> 47 <div class="article_content"> 48 {{ article_obj.content|safe }} 49 </div> 50 51 {# 点赞踩开始#} 52 <div class="clearfix"> 53 <div id="div_digg"> 54 <div class="diggit action"> 55 <span class="diggnum" id="digg_count">{{ article_obj.up_num }}</span> 56 </div> 57 <div class="buryit action"> 58 <span class="burynum" id="bury_count">{{ article_obj.down_num }}</span> 59 </div> 60 <div class="clear"></div> 61 <div class="diggword" id="digg_tips" style="color: red"> 62 </div> 63 </div> 64 </div> 65 {# 点赞踩结束#} 66 67 {# 评论楼开始#} 68 <div> 69 <ul class="list-group"> 70 {% for comment in comment_list %} 71 <li class="list-group-item"> 72 <span>#{{ forloop.counter }}楼</span> 73 <span>{{ comment.comment_time|date:‘Y-m-d H:m:s‘ }}</span> 74 <span>{{ comment.user.username }}</span> 75 <span><a class="pull-right reply" username="{{ comment.user.username }}" comment_id="{{ comment.id }}">回复</a></span> 76 <div> 77 {# // 判断当前评论是否为子评论#} 78 {% if comment.parent_id %} 79 <p>@{{ comment.parent.user.username }}</p> 80 {% endif %} 81 {{ comment.content }} 82 </div> 83 </li> 84 {% endfor %} 85 </ul> 86 </div> 87 {# 评论楼结束#} 88 89 {# 文章评论开始#} 90 {% if request.user.is_authenticated %} 91 <div> 92 <p><span class="glyphicon glyphicon-comment">发表评论</span></p> 93 <div> 94 <textarea name="comment" id="id_comment" cols="60" rows="10"></textarea> 95 </div> 96 <button class="btn btn-primary" id="id_submit">提交评论</button> 97 <span style="color: red" id="error"></span> 98 </div> 99 {% else %} 100 <li><a href="{% url ‘reg‘ %}">注册</a></li> 101 <li><a href="{% url ‘login‘ %}">登录</a></li> 102 {% endif %} 103 {# 文章评论结束#} 104 105 {% endblock %} 106 107 {% block js %} 108 <script> 109 // 给所有的action绑定事件 110 $(‘.action‘).click(function () { 111 {#alert($(this).hasClass(‘diggit‘))#} 112 let isUp = $(this).hasClass(‘diggit‘); 113 let $div = $(this); 114 // 朝后端发送ajax请求 115 $.ajax({ 116 url: ‘/up_or_down/‘, 117 type: ‘post‘, 118 data:{ 119 ‘article_id‘:‘{{ article_id }}‘, 120 ‘is_up‘:isUp, 121 ‘csrfmiddlewaretoken‘:‘{{ csrf_token }}‘, 122 }, 123 success:function (args) { 124 {#alert(args)#} 125 if(args.code==1000){ 126 {#alert(args.code);#} 127 $(‘#digg_tips‘).text(args.msg); 128 let oldNum = $div.children().text(); 129 $div.children().text(Number(oldNum)+1) 130 }else { 131 $(‘#digg_tips‘).html(args.msg) 132 } 133 } 134 }) 135 }); 136 137 // 设置一个全局变量 138 let parentId = null; 139 140 // 用户点击评论按钮朝后端发送ajax请求 141 $(‘#id_submit‘).click(function () { 142 let conTent = $(‘#id_comment‘).val(); 143 // 判断是否是子评论 如果是 需要我们将@username去除 144 if(parentId){ 145 // 找到\n对应的的索引 然后利用切片 但是切片顾头不顾尾 所以需要索引+1 146 let indexNum=conTent.indexOf(‘\n‘)+1; 147 conTent = conTent.slice((indexNum)) 148 } 149 $.ajax({ 150 url:‘/comment/‘, 151 type: ‘post‘, 152 data: { 153 ‘article_id‘:‘{{ article_obj.pk }}‘, 154 ‘content‘:conTent, 155 ‘parent_id‘:parentId, 156 ‘csrfmiddlewaretoken‘:‘{{ csrf_token }}‘, 157 }, 158 success:function (args) { 159 {#alert(args)#} 160 if(args.code==1000){ 161 $(‘#error‘).text(args.msg); 162 163 // 清空评论框 164 $(‘#id_comment‘).val(‘‘); 165 166 // 临时渲染评论楼 167 let userName =‘{{ request.user.username }}‘; 168 let temp = ` 169 <li class="list-group-item"> 170 <span>${userName}</span> 171 <div>${conTent}</div></li> 172 `; 173 // 生成的标签添加到ul标签内 174 $(‘.list-group‘).append(temp); 175 // 提交成功后清空全局的parentId 176 parentId=null; 177 } 178 } 179 }) 180 }); 181 182 // 给回复按钮绑定点击事件 183 $(‘.reply‘).click(function () { 184 // 获取用户名 185 let commentUserName=$(this).attr(‘username‘); 186 // 修改全局变量 187 parentId=$(this).attr(‘comment_id‘); 188 // 拼接信息 189 $(‘#id_comment‘).val(‘@‘+commentUserName+‘\n‘).focus() 190 }) 191 </script> 192 {% endblock %}
原文:https://www.cnblogs.com/jiaoxuefeng/p/14231140.html