首页 > 技术文章 > 博客项目实践(6)

jiaoxuefeng 2021-01-04 17:42 原文

文章详情页点赞点踩评论

展示文章内容

添加文章详情路由

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 %}

 

推荐阅读