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('
') + 1; // 先获取
所在的索引值
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+'
').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', {
'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())