zoukankan      html  css  js  c++  java
  • BBS第四天之文章详情,点赞点踩,根子评论,后台展示,文章添加(富文本编辑器)

    一.文章详情

    路由url.py:

        url(r'^(?P<username>w+)/article/(?P<pk>d+)$', views.article_detail),

    点击个人站点文章title即可关联到文章详情路由找到其视图函数

    views.py:

    def article_detail(request,username,pk):
        user = models.UserInfo.objects.filter(username=username).first()
        if not user:
            return render(request, 'error.html')
        blog = user.blog
        category_ret=models.Category.objects.all().filter(blog=blog).annotate(cou=Count('article__nid')).values_list('title','cou','nid')
        tag_ret=models.Tag.objects.all().filter(blog=blog).annotate(cou=Count('article__nid')).values_list('title','cou','nid')
        year_ret=models.Article.objects.all().annotate(month=TruncMonth('create_time')).values('month').annotate(c=Count('nid')).values_list('month','c')
    
        article=models.Article.objects.filter(nid=pk).first()
        # commit_list=article.commit_set.all()   前台模板渲染也可获取评论列表
        return render(request,'article_detail.html',locals())

    ps: 通过有名分组拿到用户名和文章id,找到该文章对象渲染到article_detail.html (用到了母版base.html)

    base.html:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>{{ blog.title }}的个人站点</title>
        <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
        <link rel="stylesheet" href="/static/css/{{ blog.theme }}">
        <script src="/static/jquery-3.3.1.js"></script>
        {% block mycss %}
    
        {% endblock %}
    </head>
    <body>
    <div class="head">
        {{ blog.site_name }}
    </div>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-3">
                <div class="panel panel-danger">
                    <div class="panel-heading">我的标签</div>
                    <div class="panel-body">
                        {% for tag in tag_ret %}
                            <p><a href="/{{ user.username }}/tag/{{ tag.2 }}">{{ tag.0 }}({{ tag.1 }})</a></p>
                        {% endfor %}
    
                    </div>
                </div>
    
                <div class="panel panel-success">
                    <div class="panel-heading">
                        <h3 class="panel-title">随笔分类</h3>
                    </div>
                    <div class="panel-body">
                        {% for category in category_ret %}
                            <p>
                                <a href="/{{ user.username }}/category/{{ category.2 }}">{{ category.0 }}({{ category.1 }})</a>
                            </p>
    
                        {% endfor %}
                    </div>
                </div>
                <div class="panel panel-success">
                    <div class="panel-heading">
                        <h3 class="panel-title">随笔档案</h3>
                    </div>
                    <div class="panel-body">
                        {% for year in year_ret %}
                            <p>
                                <a href="/{{ user.username }}/archive/{{ year.0|date:"Y-m" }}">{{ year.0|date:"Y年m月" }}({{ year.1 }})</a>
                            </p>
                        {% endfor %}
                    </div>
                </div>
            </div>
            <div class="col-md-9">
                {% block content %}
    
                {% endblock %}
            </div>
        </div>
    </div>
    </body>
    </html>

    article_detail.html:

    {% extends 'base.html' %}
    
    {% block mycss %}
        <link rel="stylesheet" href="/static/css/commoncss.css">
    {% endblock %}
    
    
    {% block content %}
        <div>
            <h4>{{ article.title }}</h4>
            <div>
                {{ article.content|safe }}
            </div>
            <div class="clearfix">
                <div id="div_digg">
                    <div class="diggit upanddown">
                        <span class="diggnum" id="digg_count">{{ article.up_num }}</span>
                    </div>
                    <div class="buryit upanddown">
                        <span class="burynum" id="bury_count">{{ article.down_num }}</span>
                    </div>
                    <div class="clear"></div>
                    <div class="diggword" id="digg_tips" style="color: red;"></div>
                </div>
            </div>
    
            <div>
                {#评论相关#}
                <div>
                    {#评论列表#}
                    <p>评论列表</p>
                    <ul class="list-group commit_content">
                        {% for commit in article.commit_set.all %}
                            <li class="list-group-item">
                                <p>
                                    <span>#{{ forloop.counter }} 楼</span>
                                    <span>{{ commit.create_time|date:"Y-m-d H:i" }}</span>
                                    <span>{{ commit.user.username }}</span>
                                    <span class="pull-right reply" username="{{ commit.user.username }}"
                                          commit_id="{{ commit.pk }}"><a>回复</a></span>
                                </p>
                                {% if commit.parent %}
                                    <p class="well">@{{ commit.parent.user.username }}----{{ commit.parent.content }}</p>
                                {% endif %}
                                {{ commit.content }}
    
    
                            </li>
                        {% endfor %}
                    </ul>
    
                </div>
                <div>
                    {#发表评论#}
                    <p>发表评论</p>
                    <p>
                        昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50"
                                  value="{{ request.user.username }}">
                    </p>
                    <p>评论内容</p>
                    <textarea name="" id="id_textarea" cols="80" rows="10">
    
                    </textarea>
                    <p>
                        <button class="btn btn-success" id="btn_submit">提交</button>
                    </p>
                </div>
    
    
            </div>
    
    
        </div>
        <script>
            var parent_id = ''
            //评论相关
            $("#btn_submit").click(function () {
                var content = $("#id_textarea").val()
    
                if (parent_id) {
                    //有值,截取前面的@姓名
                    //indexof 截取 
    的索引位置
                    var index = content.indexOf('
    ') + 1
                    content = content.slice(index)
                }
                //谁对那篇文章评论了什么内容
                $.ajax({
                    url: '/commit/',
                    type: 'post',
                    data: {
                        article_id: '{{article.pk}}',
                        content: content,
                        csrfmiddlewaretoken: '{{ csrf_token }}',
                        parent_id: parent_id
                    },
                    success: function (data) {
                        console.log(data)
                        //清除输入框的数据
                        $("#id_textarea").val("")
                        if (data.code == 100) {
                            var username = data.username
                            var reply_content = data.reply_content
                            //往后追加内容
                            if (parent_id) {
                                var parent_name = data.parent_name
                                var s = `
                                    <li class="list-group-item">
                                    <p>
                                        <span>${username}</span>
                                    </p>
                                        <p class="well">@${parent_name}</p>
                                        ${reply_content}
                                    </li>
                            `
                            } else {
                                //追加根评论的内容
                                //es6的字符串替换
    
                                var s = `
                                    <li class="list-group-item">
                                    <p>
                                        <span>${username}</span>
                                    </p>
                                        ${reply_content}
                                    </li>
                            `
                            }
    
    
                            $(".commit_content").append(s)
                        }
    
                    }
                })
    
            })
            //回复相关
            $(".reply").click(function () {
                var username = '@' + $(this).attr('username') + '
    '
                parent_id = $(this).attr('commit_id')
                //光标聚焦到该控件上
    
                $("#id_textarea").focus()
                $("#id_textarea").val(username)
    
            })
    
    
            //点赞点踩相关
            $(".upanddown").click(function () {
                //当前点击控件有没有diggit 这个类
                var is_up = $(this).hasClass('diggit')
                //拿到当前点击控件子控件的span标签对象
                var cu_span = $(this).children('span')
                //alert(is_up)
                //谁对哪篇文章点赞或点踩
                $.ajax({
                    url: '/diggit/',
                    type: 'post',
                    data: {article_id: '{{article.pk}}', is_up: is_up, csrfmiddlewaretoken: '{{ csrf_token }}'},
                    success: function (data) {
                        console.log(data)
                        $("#digg_tips").html(data.msg)
                        if (data.code == 100) {
                            {#cu_span.text(cu_span.text()+1)#}
                            //在当前点击的div下的span标签上数字加以
                            cu_span.text(Number(cu_span.text()) + 1)
                        }
                    }
                })
    
            })
        </script>
    {% endblock %}

    文章详情展示了以下内容:  文章title,  文章content (传html文件,用safe转义),点赞点踩,评论列表,评论内容:

    a.点赞点踩:

            <div class="clearfix">
                <div id="div_digg">
                    <div class="diggit upanddown">
                        <span class="diggnum" id="digg_count">{{ article.up_num }}</span>
                    </div>
                    <div class="buryit upanddown">
                        <span class="burynum" id="bury_count">{{ article.down_num }}</span>
                    </div>
                    <div class="clear"></div>
                    <div class="diggword" id="digg_tips" style="color: red;"></div>
                </div>
            </div>

    js:

     //点赞点踩相关
            $(".upanddown").click(function () {
                //当前点击控件有没有diggit 这个类
                var is_up = $(this).hasClass('diggit')
                //拿到当前点击控件子控件的span标签对象
                var cu_span = $(this).children('span')
                //alert(is_up)
                //谁对哪篇文章点赞或点踩
                $.ajax({
                    url: '/diggit/',
                    type: 'post',
                    data: {article_id: '{{article.pk}}', is_up: is_up, csrfmiddlewaretoken: '{{ csrf_token }}'},
                    success: function (data) {
                        console.log(data)
                        $("#digg_tips").html(data.msg)
                        if (data.code == 100) {
                            {#cu_span.text(cu_span.text()+1)#}
                            //在当前点击的div下的span标签上数字加以
                            cu_span.text(Number(cu_span.text()) + 1)
                        }
                    }
                })

     点赞点踩视图函数: 开启事务,将点赞点踩表创建记录的同时,把文章表的点赞或点踩数也加一

    import json
    from django.db.models import F
    def diggit(request):
        response={'code':100,'msg':None}
        #当前登陆用户id
        if request.user.is_authenticated():
            user_id=request.user.nid
            is_up=request.POST.get('is_up')
            print(type(is_up))
            print(is_up)
            is_up=json.loads(is_up)
            print(type(is_up))
            print(is_up)
            article_id=request.POST.get('article_id')
            up_ret=models.UpAndDown.objects.filter(user_id=user_id,article_id=article_id).first()
            if up_ret:
                response['code'] = 102
                response['msg'] = '您已经点过了'
            else:
                #事务性的操作
                from django.db import transaction
                #开启事务
                with transaction.atomic():
                    models.UpAndDown.objects.create(article_id=article_id,user_id=user_id,is_up=is_up)
                    if is_up:
                        #文章表点赞字段加一
                        models.Article.objects.filter(pk=article_id).update(up_num=F('up_num')+1)
                        response['msg'] = '点赞成功'
                    else:
                        models.Article.objects.filter(pk=article_id).update(down_num=F('down_num')+1)
                        response['msg'] = '点踩成功'
    
        else:
            response['code']=101
            response['msg']='请先登陆'
        return JsonResponse(response,safe=False)

    b.评论列表:

            <div>
                {#评论相关#}
                <div>
                    {#评论列表#}
                    <p>评论列表</p>
                    <ul class="list-group commit_content">
                        {% for commit in article.commit_set.all %}
                            <li class="list-group-item">
                                <p>
                                    <span>#{{ forloop.counter }} 楼</span>
                                    <span>{{ commit.create_time|date:"Y-m-d H:i" }}</span>
                                    <span>{{ commit.user.username }}</span>
                                    <span class="pull-right reply" username="{{ commit.user.username }}"
                                          commit_id="{{ commit.pk }}"><a>回复</a></span>
                                </p>
                                {% if commit.parent %}
                                    <p class="well">@{{ commit.parent.user.username }}----{{ commit.parent.content }}</p>
                                {% endif %}
                                {{ commit.content }}
    
    
                            </li>
                        {% endfor %}
                    </ul>
    
                </div>

    c.发表评论:

                <div>
                    {#发表评论#}
                    <p>发表评论</p>
                    <p>
                        昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50"
                                  value="{{ request.user.username }}">
                    </p>
                    <p>评论内容</p>
                    <textarea name="" id="id_textarea" cols="80" rows="10">
    
                    </textarea>
                    <p>
                        <button class="btn btn-success" id="btn_submit">提交</button>
                    </p>
                </div>

    js:

            var parent_id = ''
            //评论相关
            $("#btn_submit").click(function () {
                var content = $("#id_textarea").val()
    
                if (parent_id) {
                    //有值,截取前面的@姓名
                    //indexof 截取 
    的索引位置
                    var index = content.indexOf('
    ') + 1
                    content = content.slice(index)
                }
                //谁对那篇文章评论了什么内容
                $.ajax({
                    url: '/commit/',
                    type: 'post',
                    data: {
                        article_id: '{{article.pk}}',
                        content: content,
                        csrfmiddlewaretoken: '{{ csrf_token }}',
                        parent_id: parent_id
                    },
                    success: function (data) {
                        console.log(data)
                        //清除输入框的数据
                        $("#id_textarea").val("")
                        if (data.code == 100) {
                            var username = data.username
                            var reply_content = data.reply_content
                            //往后追加内容
                            if (parent_id) {
                                var parent_name = data.parent_name
                                var s = `
                                    <li class="list-group-item">
                                    <p>
                                        <span>${username}</span>
                                    </p>
                                        <p class="well">@${parent_name}</p>
                                        ${reply_content}
                                    </li>
                            `
                            } else {
                                //追加根评论的内容
                                //es6的字符串替换
    
                                var s = `
                                    <li class="list-group-item">
                                    <p>
                                        <span>${username}</span>
                                    </p>
                                        ${reply_content}
                                    </li>
                            `
                            }
    
    
                            $(".commit_content").append(s)
                        }
    
                    }
                })
    
            })
            //回复相关
            $(".reply").click(function () {
                var username = '@' + $(this).attr('username') + '
    '
                parent_id = $(this).attr('commit_id')
                //光标聚焦到该控件上
    
                $("#id_textarea").focus()
                $("#id_textarea").val(username)
    
            })

    评论视图函数:开启事务,在评论表添加记录的同时,也在文章表添加评论数

    def commit(request):
        response = {'code': 100, 'msg': None}
        # 当前登陆用户id
        if request.user.is_authenticated():
            user_id = request.user.nid
            article_id = request.POST.get('article_id')
            content=request.POST.get('content')
            parent_id=request.POST.get('parent_id')
            # 事务性的操作
            from django.db import transaction
            # 开启事务
            with transaction.atomic():
                ret=models.Commit.objects.create(article_id=article_id,content=content,user_id=user_id,parent_id=parent_id)
                models.Article.objects.filter(pk=article_id).update(comment_num=F('comment_num') + 1)
                response['username']=ret.user.username
                response['reply_content']=ret.content
                if parent_id:
                    response['parent_name'] = ret.parent.user.username
                response['msg'] = '评论成功'
    
    
    
        else:
            response['code'] = 101
            response['msg'] = '请先登陆'
        return JsonResponse(response, safe=False)

    二.后台展示,添加文章

    路由url.py:

        # 后台管理首页
        url(r'^backend/', views.home_backend),

    视图函数:

    from django.contrib.auth.decorators import login_required
    @login_required(login_url='/login/')
    def home_backend(request):
        #查询该人的所有文章
        ariticle_list=models.Article.objects.filter(blog=request.user.blog)
        return render(request,'backend/home_backend.html',locals())

    前端渲染母版backend_base.html:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>后台管理</title>
        <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
        <script src="/static/jquery-3.3.1.js"></script>
        <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    </head>
    <body>
    <div class="head" style="height: 60px;background-color: #2b669a">
        <p>后台管理</p>
    </div>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-3">
                <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
                    <div class="panel panel-default">
                        <div class="panel-heading" role="tab" id="headingOne">
                            <h4 class="panel-title">
                                <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne"
                                   aria-expanded="true" aria-controls="collapseOne">
                                    文章管理
                                </a>
                            </h4>
                        </div>
                        <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
                             aria-labelledby="headingOne">
                            <div class="panel-body">
                                <a href="/add_article/">添加文章</a>
    跳到添加文章路由
    </div> </div> <div id="xxx" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <a href="">添加随笔</a> </div> </div> </div> </div> </div> <div class="col-md-9"> <div> <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"><a href="#home" aria-controls="home" role="tab" data-toggle="tab">文章</a></li> <li role="presentation"><a href="#profile" aria-controls="profile" role="tab" data-toggle="tab">随笔</a> </li> <li role="presentation"><a href="#messages" aria-controls="messages" role="tab" data-toggle="tab">交友</a> </li> <li role="presentation"><a href="#settings" aria-controls="settings" role="tab" data-toggle="tab">相册</a> </li> </ul> <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="home"> {% block content %} {% endblock %} </div> <div role="tabpanel" class="tab-pane" id="profile">随笔</div> <div role="tabpanel" class="tab-pane" id="messages">交友</div> <div role="tabpanel" class="tab-pane" id="settings">相册</div> </div> </div> </div> </div> </div> </body> </html>

    后台管理前端home_backend.html:

    {% extends 'backend/backend_base.html' %}
    
    {% block content %}
        <table class="table table-striped">
            <thead>
            <tr>
                <th>标题</th>
                <th>评论数</th>
                <th>点赞数</th>
                <th>操作</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            {% for ariticle in ariticle_list %}
                <tr>
                    <td><a href="/{{ request.user.username }}/article/{{ ariticle.pk }}">{{ ariticle.title }}</a></td>
    跳到文章详情路由 <td>{{ ariticle.commit_num }}</td> <td>{{ ariticle.up_num }}</td> <td><a href="">删除</a></td> <td><a href="">编辑</a></td> </tr> {% endfor %} </tbody> </table> {% endblock %}

     添加文章路由:

        # 添加文章
        url(r'^add_article/', views.add_article),

    添加文章视图函数:(用bs4来解析html文档,删除script标签内容来防止xss

    @login_required(login_url='/login/')
    def add_article(request):
        if request.method=='GET':
            return render(request,'backend/add_article.html')
        else:
            title=request.POST.get('title')
            text_content=request.POST.get('text_content')
            #通过bs4 处理xss攻击,html文档解析库
            #pip3 install beautifulsoup4
            from bs4 import BeautifulSoup
            soup=BeautifulSoup(text_content,'html.parser')
            #查找所有的标签
            tags=soup.find_all()
            for tag in tags:
                if tag.name=='script':
                    #从文档中删除该标签
                    tag.decompose()
            #soup.text 文档的内容,不包含标签
            desc=soup.text[0:150]
            models.Article.objects.create(title=title,desc=desc,content=str(soup),blog=request.user.blog)
            return redirect('/backend/')

     添加文章add_article.html(借助富文本编辑器):

    {% extends 'backend/backend_base.html' %}
    
    {% block content %}
    
        <div>
            <p>添加文章</p>
            <form action="/add_article/" method="post">
                {% csrf_token %}
                <div class="form-group">
                    <label for="id_name">文章标题</label>
                    <input type="text" name="title" id="id_title" class="form-control">
                </div>
                <p>内容(KindEditor编辑器,不支持拖放/粘贴上传图片) </p>
                <textarea name="text_content" id="editor_id" cols="30" rows="10"></textarea>
                <p>
                    <button class="btn btn-success">提交</button>
                </p>
            </form>
    
        </div>
        <script charset="utf-8" src="/static/kindeditor/kindeditor-all.js"></script>
    
        <script>
    
            KindEditor.ready(function (K) {
                window.editor = K.create('#editor_id', {
                     '100%',
                    height: '400px',
                    resizeType: 0,
                    {#items: [#}
                    {#    'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste',#}
                    {#    'plainpaste', 'wordpaste', '|'#}
                    {#]#}
                    uploadJson: '/uploadimg/',
                    extraFileUploadParams: {
                        csrfmiddlewaretoken: '{{ csrf_token }}',
                    }
    
                });
            });
        </script>
    {% endblock %}

    在富文本编辑器中上传图片,图片地址放在media/file下即可:

    @login_required(login_url='/login/')
    def uploadimg(request):
        response={
            "error" : 0,
            "url" : None
        }
        fil=request.FILES.get('imgFile')
        with open('media/file/'+fil.name,'wb') as f:
            for line in fil:
                f.write(line)
            response['url']='/media/file/'+fil.name
        return JsonResponse(response)
  • 相关阅读:
    LINQ操作符一:Select
    DataGridView使用技巧十二:DataGridView Error图标表示的设定
    DataGridView使用技巧十一:DataGridView用户输入时,单元格输入值的设定
    DataGridView使用技巧十:单元格表示值的自定义
    DataGridView使用技巧九:DataGridView的右键菜单(ContextMenuStrip)
    清除DataGridView显示的数据
    SQL Server查询某个字段存在哪些表中
    DataGridView使用技巧八:设置单元格的ToolTip
    DataGridView使用技巧七:列顺序的调整、操作行头列头的标题
    csvkit---python一个牛逼到不行的csv处理库
  • 原文地址:https://www.cnblogs.com/sima-3/p/11402823.html
Copyright © 2011-2022 走看看