zoukankan      html  css  js  c++  java
  • BBS项目之文章评论

    BBS项目之文章评论

    需求分析

    #  需求1
    不许匿名用户评论,提供登录/注册的接口
    #  需求2
    可以评论别人的文章,也可以回复别人对自己文章的评论(即根评论与子评论)
    #  需求3
    评论的渲染方式有两种,点击评论按钮,使用DOM操作临时渲染评论楼;刷新URL,使用render渲染评论楼
    #  需求4
    给回复按钮绑定两个属性,当前根评论的用户,以及评论的主键值
    

    数据库表设计

    class Comment(models.Model):
        """评论表"""
        user = models.ForeignKey(to='UserInfo')
        article = models.ForeignKey(to='Article')
        content = models.CharField(verbose_name='评论内容', max_length=255)
        comment_time = models.DateTimeField(verbose_name='评论时间', auto_now_add=True)
        # 自关联
        parent = models.ForeignKey(to='self', null=True)  # 有些评论就是根评论
    

    这里需要注意的是:

    我们知道根评论与子评论的区别在于,子评论多了一个parent_id,因此评论表中的自关联字段parent必须设置null=True,否则,所有的评论都是子评论,没有根评论。

    代码

    前端

    {% if request.user.is_authenticated %}
                <div>
                    <a href="#" style="text-decoration: none" title="发表评论"><img src="/static/img/comment.png" alt=""
                                                                                style=" 20px;height: 20px">&nbsp;&nbsp;发表评论</a>
                    <div>
                        <div>
                            <span style="color: red" id="thanks"></span>
                        </div>
                        <textarea name="comment" id="id_comment" cols="60" rows="10" placeholder="支持Markdown"></textarea>
                    </div>
                    <button class="btn btn-primary" id="id_submit">提交评论</button>
                    <span style="color: red" id="error"></span>
                </div>
            {% else %}
                <div>
                    <a href="{% url 'login' %}" style="text-decoration: none">登录</a>&nbsp;&nbsp;
                    <a href="#" class="register_model" style="text-decoration: none">注册</a>
                </div>
            {% endif %}
            
            
            //设置一个全局的parentId
            let parentId = null;
            //用户点击评论按钮后直接朝后端发送ajax请求
            $('#id_submit').on('click', function () {
                let content = $('#id_comment').val();
                //判断当前的评论是否为子评论,如果是去除 /n之前的字符
                if (parentId) {
                    //利用切片操作(找到
    的索引,然后利用切片,切片顾头不顾尾)
                    let indexNum = content.indexOf('
    ') + 1;
                    content = content.slice(indexNum); //将indexNum之前的所有数据切除,只保留后面的一部分
                }
                $.ajax({
                    url: '/comment/',
                    type: 'post',
                    data: {
                        'article_id': '{{ article_obj.pk }}',
                        'content': content,
                        'parent_id': parentId, //如果没有点击回复parentId就是Null
                        'csrfmiddlewaretoken': '{{ csrf_token }}',
                    },
                    success: function (args) {
                        if (args.code === 1600) {
                            //将评论框的内容清空
                            $('#id_comment').val('');
                            //感谢回复
                            $('#thanks').html('感谢您的回复☺:');
                            //临时渲染评论楼
                            let username = '{{ request.user.username }}';
                            let temp = `
                                <a href='#' style="text-decoration: none;" title='发表评论'><img src="/static/img/comment.png" alt="" style=" 20px;height: 20px">&nbsp;&nbsp;${username}</a>
                                <div class="panel panel-info">
                                    <div class="panel-body">
                                        ${content}
                                    </div>
                                </div>`;
                            $('.content-group').append(temp);
                            //清空全局的parentId字段
                            parentId = null;
                        }
                    }
                })
            });
    
    
    

    后端

    def comment(request):
        # 自己也可以给自己评论
        if request.is_ajax():
            back_dict = {'code': 1600, 'msg': ''}
            if request.method == 'POST':
                if request.user.is_authenticated:
                    article_id = request.POST.get('article_id')
                    content = request.POST.get('content')
                    # 获取父评论
                    parent_id = request.POST.get('parent_id')
                    # 直接操作评论表 存储数据  两张表
                    # 开事务
                    with transaction.atomic():
                        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_dict['msg'] = '评论成功'
                else:
                    back_dict['code'] = 1601
                    back_dict['msg'] = '用户未登录'
                return JsonResponse(back_dict)
    
    
  • 相关阅读:
    jMeter 里 CSV Data Set Config Sharing Mode 的含义详解
    如何使用 jMeter Parallel Controller
    使用 Chrome 开发者工具 coverage 功能分析 web 应用的渲染阻止资源的执行分布情况
    使用 Chrome 开发者工具的 lighthouse 功能分析 web 应用的性能问题
    关于 SAP 电商云首页加载时触发的 OCC API 请求
    SAP UI5 确保控件 id 全局唯一的实现方法
    SAP 电商云 Accelerator 和 Spartacus UI 的工作机制差异
    介绍一个好用的能让网页变成黑色背景的护眼 Chrome 扩展应用
    Chrome 开发者工具 performance 标签页的用法
    Client Side Cache 和 Server Side Cache 的区别
  • 原文地址:https://www.cnblogs.com/surpass123/p/13150018.html
Copyright © 2011-2022 走看看