标签:dig 查找 userinfo parent 首页 message jquery sheet update
一.文章详情
路由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 截取 \n的索引位置 var index = content.indexOf(‘\n‘) + 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‘) + ‘\n‘ 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 截取 \n的索引位置 var index = content.indexOf(‘\n‘) + 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‘) + ‘\n‘ 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‘, { width: ‘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)
BBS第四天之文章详情,点赞点踩,根子评论,后台展示,文章添加(富文本编辑器)
标签:dig 查找 userinfo parent 首页 message jquery sheet update
原文地址:https://www.cnblogs.com/sima-3/p/11402823.html