HTML
{% extends 'base.html' %} {% block css %} <style> #div_digg { float: right; margin-bottom: 10px; margin-right: 30px; font-size: 12px; width: 128px; text-align: center; margin-top: 10px; } .diggit { float: left; width: 46px; height: 52px; background: url('/static/image/upup.gif') no-repeat; text-align: center; cursor: pointer; margin-top: 2px; padding-top: 5px; } .buryit { float: right; margin-left: 20px; width: 46px; height: 52px; background: url('/static/image/downdown.gif') no-repeat; text-align: center; cursor: pointer; margin-top: 2px; padding-top: 5px; } .clear { clear: both; } .diggword { margin-top: 5px; margin-left: 0; font-size: 12px; color: gray; } </style> {% endblock %} {% block content %} <h1>{{ article_obj.title }}</h1> {{ article_obj.content|safe }} {# 点赞点踩前端样式#} <div class="clearfix"> <div> <div id="div_digg"> <div class="diggit action" > <span class="diggnum" id="digg_count">{{ article_obj.up_num }}</span> </div> <div class="buryit action"> <span class="burynum" id="bury_count">{{ article_obj.down_num }}</span> </div> <div class="clear"></div> <div class="diggword" id="digg_tips"> <span style="color: red" id="id_info"></span> </div> </div> </div> </div> {# 点赞点踩结束#} {# 评论楼渲染开始#} {# #51楼 2018-12-05 15:50 漏网的小鱼 #} <h4>评论列表:</h4> <ul class="list-group"> {% for comment in page_queryset %} <li class="list-group-item"> <div> <span>#{{ forloop.counter }}楼</span> <span>{{ comment.create_time|date:'Y-m-d' }}</span> <span><a href="/{{ comment.user.username }}/">{{ comment.user.username }}</a></span> <span class="pull-right reply" username="{{ comment.user.username }}" comment_id="{{ comment.pk }}"><a>回复</a></span> </div> {% if comment.parent %} <p><a href="#">@</a>{{ comment.parent.user.username }}</p> {% endif %} {{ comment.content }} </li>n {% endfor %} {{ page_obj.page_html|safe }} </ul> {# 评论楼渲染结束#} {# 评论样式开始#} <div> <p><span class="glyphicon glyphicon-comment"></span>发表评论</p> <p> 昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50" value="{{ request.user.username }}"> </p> <p>评论内容:</p> <p> <textarea name="" id="id_comment" cols="60" rows="10" ></textarea> </p> <p> <input type="button" class="btn btn-primary" value="提交评论" id="id_submit"> </p> </div> {# 评论样式结束#} <script> // 点赞点踩逻辑代码 $('.action').click(function () { var isUp = $(this).hasClass('diggit'); var $spanEle = $(this).children(); $.ajax({ url:'/up_or_down/', type:'post', data:{'is_up':isUp,'article_id':{{ article_obj.pk }},'csrfmiddlewaretoken':'{{ csrf_token }}'}, success:function (data) { if (data.code == 2000){ $('#id_info').html(data.msg); $spanEle.text(Number($spanEle.text()) + 1); }else{ $('#id_info').html(data.msg) } } }) }); var parentId = null; // 定义一个全局的parantId变量名 $("#id_submit").click(function () { var comment = $('#id_comment').val(); if (parentId){ var nIndex = comment.indexOf('\n') + 1; // 先获取\n所在的索引值 comment = comment.slice(nIndex); // 将comment中的@人名清空掉 } $.ajax({ url:'/comment/', type:'post', data:{ 'comment':comment, 'article_id':{{ article_obj.pk }}, 'csrfmiddlewaretoken':'{{ csrf_token }}', 'parent_id':parentId }, success:function (data) { if(data.code == 2000){ var userName = '{{ request.user.username }}'; // 获取用户名 var comment = $('#id_comment').val(); // 获取评论内容 var tempStr = ` // 动态生成li标签 <li class="list-group-item"> <div> <span class='glyphicon glyphicon-comment'></span><span>${userName}:</span> </div> ${comment} </li> `; $('.list-group').append(tempStr); // 查找url标签 将上面的字符串追加到ul标签内 $('#id_comment').val(''); parentId = null; } } }) }); // 点击回复按钮发生了下面三件事 $('.reply').click(function () { var userName = $(this).attr('username'); // 获取当前回复按钮所对应的根评论的用户名 $('#id_comment').html('@'+userName+'\n').focus(); // .focus()自动获取焦点 parentId = $(this).attr('comment_id'); // 将全局的parentId修改 }) </script> {% endblock %}
{% extends 'backend/backendbase.html' %} {% block content %} <h3>添加文章</h3> <hr> <form action="" method="post"> {% csrf_token %} <p>标题</p> <input type="text" name="title" id="id_title" class="form-control"> <p>内容(kindeditor编辑器,支持拖放/粘贴上传图片)</p> <p> <textarea name="content" id="id_content" cols="30" rows="10"></textarea> </p> <input type="submit" value="发布" class="btn btn-danger"> </form> <script charset="utf-8" src="/static/kindeditor/kindeditor-all-min.js"></script> <script> KindEditor.ready(function (K) { window.editor = K.create('#id_content', { width: '100%', height:'450px', resizeType:0, uploadJson : '/upload_img/', // 控制文件上传的位置 extraFileUploadParams : { 'csrfmiddlewaretoken':'{{ csrf_token }}' } }); }); </script> {% endblock %}
views
from django.contrib.auth.decorators import login_required from django.db import transaction # django中开启事务 需要先倒入该模块 @login_required def comment(request): back_dic = {'code':None,'msg':''} if request.is_ajax(): comment = request.POST.get('comment') article_id = request.POST.get('article_id') parent_id = request.POST.get('parent_id') with transaction.atomic(): # 在with代码块写的就是一个事务 models.Article.objects.filter(pk=article_id).update(comment_num = F('comment_num') + 1) # 文章表修改comment_num字段 models.Comment.objects.create(user=request.user,article_id=article_id,content=comment,parent_id=parent_id) # 评论表里面新增数据 back_dic['code'] = 2000 back_dic['msg'] = '评论成功' return JsonResponse(back_dic) # 后台管理 @login_required def backend(request): article_list = models.Article.objects.filter(blog=request.user.blog) page_obj = Pagination(current_page=request.GET.get('page', 1), all_count=article_list.count()) page_queryset = article_list[page_obj.start:page_obj.end] return render(request,'backend/backend.html',locals()) from bs4 import BeautifulSoup def add_article(request): if request.method == 'POST': title = request.POST.get('title') content = request.POST.get('content') res = BeautifulSoup(content,'html.parser') # 能够帮我拿到当前用户写的所有的标签 tags = res.find_all() for tag in tags: if tag.name == 'script': tag.decompose() # 删除指定的标签 desc = res.text[0:150] # 用户输入的文本值切片 models.Article.objects.create(title=title,content=str(res),desc=desc,blog=request.user.blog) return redirect('/backend/') return render(request,'backend/add_article.html') from BBS import settings import os def upload_img(request): back_dic = {'error':''} if request.method == 'POST': img_obj = request.FILES.get('imgFile') path = os.path.join(settings.BASE_DIR,'media','upload_img') # 规定编辑器上传的图片全部放到media文件夹里面的upload_img文件夹下 if not os.path.exists(path): os.mkdir(path) file_path = os.path.join(path,img_obj.name) with open(file_path,'wb') as f: for line in img_obj: f.write(line) back_dic['error'] = 0 back_dic['url'] = '/media/upload_img/%s'%img_obj.name # 2.将文件路径返回给前端 """ //成功时 { "error" : 0, "url" : "http://www.example.com/path/to/file.ext" } //失败时 { "error" : 1, "message" : "错误信息" } """ return JsonResponse(back_dic) @login_required def set_avatar(request): username = request.user.username if request.method == 'POST': new_avatar = request.FILES.get('new_avatar') # models.Userinfo.objects.filter(pk=request.user.pk).update(avatar=new_avatar) # 如果用queryset对象更新头像 不会自动帮你拼接前缀 user_obj = models.Userinfo.objects.filter(pk=request.user.pk).first() user_obj.avatar = new_avatar user_obj.save() return redirect('/home/') return render(request,'set_avatar.html',locals())