• BBS项目之 点赞点踩 评论 编辑 文章详情展示 编辑文章 评论后发送邮件 后台管理页面搭建 富文本编辑器的使用


    BBS项目之 点赞点踩 评论  编辑 文章详情展示  编辑文章 

    文章详情前端

      1 {% extends 'base.html' %}
      2 
      3 {% block title %}
      4     {{ article.title }}
      5 {% endblock %}
      6 
      7 {% block css %}
      8     <link rel="stylesheet" href="/static/css/mycss.css">
      9 {% endblock %}
     10 
     11 
     12 {% block content %}
     13     <div>
     14         <h3 class="text-center">{{ article.title }}</h3>
     15         <hr>
     16         <div>
     17             {{ article.content|safe }}
     18         </div>
     19         <!--
     20         点赞点踩
     21         -->
     22         <div class="clearfix">
     23             <div id="div_digg">
     24                 <div class="diggit action">
     25                     <span class="diggnum" id="digg_count">{{ article.up_num }}</span>
     26                 </div>
     27                 <div class="buryit action">
     28                     <span class="burynum" id="bury_count">{{ article.down_num }}</span>
     29                 </div>
     30                 <div class="clear"></div>
     31                 <div class="diggword" id="digg_tips" style="color: red;">
     32                 </div>
     33             </div>
     34         </div>
     35         <hr>
     36         <!--
     37         评论列表和评论输入框
     38         #1楼 2018-03-22 13:33 Yif.Z     回复
     39         峰哥,什么视频时候这个在线上班更新啊
     40         -->
     41         <div>
     42             评论列表
     43             <ul class="list-group">
     44                 {% for comment in comment_list %}
     45                     <li class="list-group-item">
     46                         <div>
     47                             <span>#{{ forloop.counter }}楼</span>
     48                             <span>{{ comment.create_time|date:'Y-m-d H-i-s' }}</span>
     49                             <span><a href="/{{ comment.user.username }}">{{ comment.user.username }}</a></span>
     50                             <span class="pull-right id_replay" username="{{ comment.user.username }} "
     51                                   parent="{{ comment.pk }}"><a>回复</a></span>
     52                         </div>
     53                         <hr>
     54                         <div>
     55                             {% if comment.commit_id_id %}
     56                                 <p>@{{ comment.commit_id.user.username }}</p>
     57                                 <p>{{ comment.content }}</p>
     58                             {% else %}
     59                                 {{ comment.content }}
     60                             {% endif %}
     61 
     62                         </div>
     63                     </li>
     64                 {% endfor %}
     65             </ul>
     66 
     67         </div>
     68         {% if request.user.is_authenticated %}
     69             <div>
     70                 <p class="glyphicon glyphicon-copyright-mark">发表评论</p>
     71                 <p><textarea name="" id="id_text" cols="180" rows="10"></textarea></p>
     72                 <p>
     73                     <button class="btn btn-success" id="id_comment">发表评论</button>
     74                 </p>
     75             </div>
     76         {% else %}
     77             <div>
     78                 登录后才能发表评论,立即 <a href="/login/">登录</a> 或 <a href="/register/">注册</a>, 访问 网站首页
     79             </div>
     80         {% endif %}
     81 
     82 
     83     </div>
     84 {% endblock %}
     85 
     86 {% block script %}
     87     <script>
     88         //把parent_id定义成全局变量
     89         var parent_id = ''
     90         $(".action").click(function () {
     91             var is_up = $(this).hasClass('diggit')
     92             var span = $(this).children('span')
     93             $.ajax({
     94                 url: '/upanddown/',
     95                 method: 'post',
     96                 data: {
     97                     article_id: '{{ article.id }}',
     98                     is_up: is_up,
     99                     csrfmiddlewaretoken: '{{ csrf_token }}'
    100                 },
    101                 success: function (data) {
    102                     console.log(data)
    103                     $('#digg_tips').html(data.msg)
    104                     if (data.code == 100) {
    105                         //点赞或者点踩的数字加一
    106                         var num = Number(span.html()) + 1
    107                         span.html(num)
    108                     }
    109 
    110                 }
    111             })
    112 
    113         })
    114 
    115 
    116         $('#id_comment').click(function () {
    117 
    118             let content = $('#id_text').val()
    119             if (parent_id) {
    120                 //这表示子评论
    121                 //取到字符串第一个
    的位置索引,是一个数字
    122                 let i = content.indexOf('
    ') + 1
    123                 //从 
    +1的位置开始截取,截取到最后
    124                 content = content.slice(i)
    125             }
    126             $.ajax({
    127                 url: '/comment/',
    128                 method: 'post',
    129                 data: {
    130                     article_id: '{{ article.id }}',
    131                     content: content,
    132                     parent: parent_id,
    133                     csrfmiddlewaretoken: '{{ csrf_token }}'
    134                 },
    135                 success: function (data) {
    136                     console.log(data)
    137 
    138 
    139                     if (data.code == 100) {
    140 
    141                         let username = data.username
    142                         let res_content = data.content
    143                         let parent_name = data.parent_name
    144 
    145                         let ss = ``
    146                         if (parent_id) {
    147                             ss = `<li class="list-group-item">
    148                                 <div>
    149                                     <span class="glyphicon glyphicon-comment">${username}</span>
    150                                 </div>
    151                                 <div>
    152                                 <p>@${parent_name}</p>
    153                                     ${res_content}
    154                                 </div>
    155                             </li>`
    156                         } else {
    157                             ss = `<li class="list-group-item">
    158                                 <div>
    159                                     <span class="glyphicon glyphicon-comment">${username}</span>
    160 
    161                                 </div>
    162                                 <div>
    163                                     ${res_content}
    164                                 </div>
    165                             </li>`
    166                         }
    167 
    168                         //清空输入框
    169                         $('#id_text').val('')
    170                         //把ss追加到评论列表的后面
    171                         $('.list-group').append(ss)
    172                         //把parent_id置空
    173                         parent_id = ''
    174                     }
    175 
    176 
    177                 }
    178             })
    179 
    180         })
    181 
    182         $('.id_replay').click(function () {
    183             let username = $(this).attr('username')
    184             parent_id = $(this).attr('parent')
    185 
    186             $('#id_text').val('@' + username + '
    ').focus()
    187         })
    188     </script>
    189 {% endblock %}

    点赞 点踩前端

     <script>
          
            $(".action").click(function () {
                var is_up = $(this).hasClass('diggit')
                var span = $(this).children('span')
                $.ajax({
                    url: '/upanddown/',
                    method: 'post',
                    data: {
                        article_id: '{{ article.id }}',
                        is_up: is_up,
                        csrfmiddlewaretoken: '{{ csrf_token }}'
                    },
                    success: function (data) {
                        console.log(data)
                        $('#digg_tips').html(data.msg)
                        if (data.code == 100) {
                            //点赞或者点踩的数字加一
                            var num = Number(span.html()) + 1
                            span.html(num)
                        }
    
                    }
                })
    
            })

    点赞点踩后端

    def upanddown(request):
        res = {'code': 100, 'msg': ''}
        if request.user.is_authenticated:
            # article表中数字加1,在点赞点踩表中记录一条
            # 这个人对该文章只能点赞或者点踩一次
            # 先查一下,如果有记录了,就不能再点了
            article_id = request.POST.get('article_id')
            user_id = request.user.id
            is_up = request.POST.get('is_up')  # is_up是一个字符串
            print(type(is_up))
            # if is_up=='true':
            #     is_up=True
            # else:
            #     is_up = False
            is_up = json.loads(is_up)
            print(type(is_up))
            res_1 = models.UpAndDown.objects.filter(article_id=article_id, user_id=user_id).count()
            if res_1:
                res['code'] = 101
                res['msg'] = '已经点过了'
            else:
                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)
                        res['msg'] = '点赞成功'
                    else:
                        models.Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1)
                        res['msg'] = '点踩成功'
    
        else:
            res['code'] = 109
            res['msg'] = '请先<a href="/login/">登录</a>'
        return JsonResponse(res)

    评论前端

    <script>
            //把parent_id定义成全局变量
            var parent_id = ''
             $('#id_comment').click(function () {
    
                let content = $('#id_text').val()
                if (parent_id) {
                    //这表示子评论
                    //取到字符串第一个
    的位置索引,是一个数字
                    let i = content.indexOf('
    ') + 1
                    //从 
    +1的位置开始截取,截取到最后
                    content = content.slice(i)
                }
                $.ajax({
                    url: '/comment/',
                    method: 'post',
                    data: {
                        article_id: '{{ article.id }}',
                        content: content,
                        parent: parent_id,
                        csrfmiddlewaretoken: '{{ csrf_token }}'
                    },
                    success: function (data) {
                        console.log(data)
    
    
                        if (data.code == 100) {
    
                            let username = data.username
                            let res_content = data.content
                            let parent_name = data.parent_name
    
                            let ss = ``
                            if (parent_id) {
                                ss = `<li class="list-group-item">
                                    <div>
                                        <span class="glyphicon glyphicon-comment">${username}</span>
                                    </div>
                                    <div>
                                    <p>@${parent_name}</p>
                                        ${res_content}
                                    </div>
                                </li>`
                            } else {
                                ss = `<li class="list-group-item">
                                    <div>
                                        <span class="glyphicon glyphicon-comment">${username}</span>
    
                                    </div>
                                    <div>
                                        ${res_content}
                                    </div>
                                </li>`
                            }
    
                            //清空输入框
                            $('#id_text').val('')
                            //把ss追加到评论列表的后面
                            $('.list-group').append(ss)
                            //把parent_id置空
                            parent_id = ''
                        }
    
    
                    }
                })
    
            })
    
            $('.id_replay').click(function () {
                let username = $(this).attr('username')
                parent_id = $(this).attr('parent')
    
                $('#id_text').val('@' + username + '
    ').focus()
            })
        </script>

    评论后端

    def comment(request):
        res = {'code': 100, 'msg': ''}
        if request.is_ajax():
            article_id = request.POST.get('article_id')
            content = request.POST.get('content')
            parent = request.POST.get('parent')
            if request.user.is_authenticated:
                article = models.Commit.objects.create(user=request.user, article_id=article_id, content=content,
                                                       commit_id_id=parent)
                models.Article.objects.filter(pk=article_id).update(commit_num=F('commit_num') + 1)
                res['msg'] = '评论成功'
                res['username'] = article.user.username
                res['content'] = article.content
                if parent:
                    res['parent_name'] = article.commit_id.user.username
    
                # 发送邮件(同步操作) 课堂上使用的是这个
                from django.core.mail import send_mail
                # send_mail('您的文章:%s被评论了'%'git从入门到放弃','%s评论了%s'%(request.user.username,'写的真好'),settings.EMAIL_HOST_USER,
                #                                      ["1063926627@qq.com",'laichuangdelaoji@gmail.com'])


             # 通过多线程,异步操作 from threading import Thread t=Thread(target=send_mail,args=('您的文章:%s被评论了'%'git从入门到放弃','%s评论了%s'%(request.user.username,'写的真好'),settings.EMAIL_HOST_USER,["1063926627@qq.com",'laichuangdelaoji@gmail.com'])) t.start() else: res['code'] = 109 res['msg'] = '请先登录' return JsonResponse(res)

    发送邮件后端settings配置

    EMAIL_HOST = 'smtp.qq.com'  # 如果是 163 改成 smtp.163.com   以什么邮箱发送
    EMAIL_PORT = 465    # 端口号
    EMAIL_HOST_USER = '2209000808@qq.com'  # 帐号 发送者邮箱账号
    EMAIL_HOST_PASSWORD = 'wikeggxagkmmdjdj'  # 密码 不是密码, 授权码
    DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
    EMAIL_USE_SSL = True   #使用ssl,qq只支持这种

    新增文章前端代码

    {% extends 'backend/base.html' %}
    
    
    {% block content %}
        <div>
        <h4>新增文章</h4>
        <form action="" method="post">
            {% csrf_token %}
            <div class="form-group">
                <label> 标题</label>
                <input type="text" name="title" class="form-control">
            </div>
            <div class="form-group">
                <label for="">内容</label>
                <textarea name="content" id="editor_id" cols="80" rows="10" class="form-control"></textarea>
            </div>
            <div>
            个人分类
                {% for category in category_list %}
                    <div class="radio">
                        <label for="">
                            <input type="radio" name="category" value="{{ category.id }}">
                            {{ category.name }}
                        </label>
                    </div>
    
                {% endfor %}
            </div>
        <div>
            个人标签
            {% for tag in tag_list %}
                <div class="checkbox">
                    <label for="">
                        <input type="checkbox" name="tag" value="{{ tag.id }}">
                        {{ tag.name }}
                    </label>
    
                </div>
    
            {% endfor %}
        </div>
        <div class="text-center">
            <input type="submit" class="btn btn-success" value="提交">
    
        </div>
        </form>
        </div>
    {% endblock %}
    
    
    {% block script %}
    
        <script charset="utf-8" src="/static/kindeditor/kindeditor-all.js"></script>
        <script>
        KindEditor.ready(function (k) {
            window.editor = k.create('#editor_id',{
                '100%',
                height:'500px',
                resizeType:'/upload_img/',
                filePostName:'myfile',
                //额外带的参数
                extraFileUploadParams:{
                    csrfmiddlewaretoken: '{{ csrf_token }}',
                }
            })
    
        })
    
        </script>
    
    
    {% endblock %}
    View Code

    富文本编辑器前端

    <script charset="utf-8" src="/static/kindeditor/kindeditor-all.js"></script>
        <script>
        KindEditor.ready(function (k) {
            window.editor = k.create('#editor_id',{
                '100%',
                height:'500px',
                resizeType:'/upload_img/',
                filePostName:'myfile',
                //额外带的参数
                extraFileUploadParams:{
                    csrfmiddlewaretoken: '{{ csrf_token }}',
                }
            })
    
        })

    新增文章 后端代码

    @login_required(login_url='/login/')
    def new_article(request):
        if request.method == 'GET':
            category_list = models.Category.objects.filter(blog_id=request.user.blog)
            tag_list = models.Tag.objects.filter(blog=request.user.blog)
            print(category_list)
            return render(request, 'backend/add_article.html', locals())
        else:
    
            title = request.POST.get('title')
            content = request.POST.get('content')
            category = request.POST.get('category')
            tags = request.POST.getlist('tag')
            # desc = content[0:90] # 会带着标签
            soup = BeautifulSoup(content, 'html.parser')
            desc = soup.text[0:90]  # 去掉所有标签后的文本
            # 把script标签干掉
            res_script = soup.find_all('script')
            for script in res_script:
                script.decompose()  # 删除script标签
    
            article = models.Article.objects.create(title=title, content=str(soup), desc=desc, blog=request.user.blog,
                                                    category_id=category)
    
            # 存tag(自动生成第三张表)
            # article.tag.add(*tag)
            # 手动做
            # for tag in tags:
            #     models.TagToArticle.objects.create(article_id=article.pk,tag_id=tag)
    
            # 批量插入
            ll = []
            for tag in tags:
                ll.append(models.TagToArticle(article_id=article.pk, tag_id=tag))
            models.TagToArticle.objects.bulk_create(ll)
    
            return redirect('/backend_index/')
    View Code

    上传图片后端代码

    def upload_img(request):
        res = {'error':0}
        print(request.FILES)
        try:
            # 存图片
            file = request.FILES.get('myfile')
            print(file,'上传的图片')
            path = os.path.join(settings.BASE_DIR, 'media', 'avatar', file.name)
            with open(path, 'wb') as f:
                for line in file:
                    f.write(line)
            res['url'] = '/media/avatar/' + file.name
        except Exception as e:
            res['error'] = 1
            res['message'] = str(e)
        return JsonResponse(res)
    View Code

    更新文章后端代码

    from bs4 import BeautifulSoup
    
    @login_required(login_url='/login/')
    def update_article(request,id):
        if request.method == 'GET':
            article = models.Article.objects.get(id=id)
            category_list = models.Category.objects.filter(blog=request.user.blog)
            tag_list = models.Tag.objects.filter(blog=request.user.blog)
            # category_list = models.Category.objects.filter(blog=request.user.blog).annotate(
            #     num=Count('article__id')).values_list(
            #     'name', 'num', 'id'
            # )
    
    
            return render(request,'backend/update_article.html',locals())
        else:
            title = request.POST.get('title')
            content = request.POST.get('content')
            category = request.POST.get('category')
            tags = request.POST.getlist('tag')
            #desc = content[0:90]  #会带着标签
            soup = BeautifulSoup(content,'html.parser')
            desc = soup.text[0:90]  #去掉所有标签后的文本
            #把script标签干掉
            res_script = soup.find_all('script')
    
            for script in res_script:
                script.decompose()  #删除script标签
    
            article = models.Article.objects.filter(pk=id)
            article.update(title=title,content=str(soup),desc=desc,category_id=category)
            ll = []
            for tag in tags:
                ll.append(models.TagToArticle(article_id=article.first().pk, tag_id=tag))
            models.TagToArticle.objects.bulk_create(ll)
            return redirect('/backend_index/')
    View Code

    更新文章前端代码

    {% extends 'backend/base.html' %}
    
    
    {% block content %}
        <div>
        <h4>修改文章</h4>
            <form action="/update_article/{{ article.pk }}/" method="post">
            {% csrf_token %}
        <div class="form-group">
            <label for="">标题</label>
            <input type="text" name="title" class="form-control" value="{{ article.title }}">
                </div>
                <div class="form-group">
                    <label for="">内容</label>
                    <textarea name="content" id="editor_id" cols="80" rows="10" class="form-control">
                        {{ article.content }}
                    </textarea>
                </div>
                <div>
                    个人分类
                    {% for category in category_list %}
                        <div class="radio">
                            <label>
                                <input type="radio" name="category" value="{{ category.id }}">
                                {{ category.name }}
                            </label>
                        </div>
                    {% endfor %}
    
                </div>
                <div>
                    个人标签
                    {% for tag in tag_list %}
                        <div class="checkbox">
                            <label>
                                <input type="checkbox" name="tag" value="{{ tag.id }}">
                                {{ tag.name }}
                            </label>
                        </div>
                    {% endfor %}
    
                </div>
                <div class="text-center">
                    <input type="submit" class="btn btn-success" value="提交">
                </div>
            </form>
    
    
        </div>
    {% endblock %}
    {% block script %}
    
    
        <script charset="utf-8" src="/static/kindeditor/kindeditor-all.js"></script>
        <script>
            KindEditor.ready(function (K) {
                window.editor = K.create('#editor_id', {
                     '100%',
                    height: '500px',
                    resizeType: 1,
                    uploadJson:'/upload_img/',
                    filePostName:'myfile',
                    //额外带的参数
                    extraFileUploadParams : {
                          csrfmiddlewaretoken: '{{ csrf_token }}',
    
                    }
    
    
                });
            });
        </script>
    {% endblock %}
    View Code
  • 相关阅读:
    Codeforces Round #171 (Div. 2)
    ACdream 1079 郭式树
    HDOJ 1517 博弈论
    ACdream 1080 面面数
    博弈论 Nim 博弈
    Codeforces Round #172 (Div. 2)
    ACdream 1084 同心树
    STL bitset
    博弈论 bash博弈
    POJ 3261 后缀数组
  • 原文地址:https://www.cnblogs.com/ltyc/p/13975157.html
Copyright © 2020-2023  润新知