BBS ——事务四大特性,,评论render显示,,根评论提交和ajax的显示,,子评论提交--ajax显示,,后台管理页面,,删除文章
事务:四大特性
-原子性
-一致性
-持久性
-隔离性
# 点赞点踩案例
1 点赞点踩增加记录
2 文章表中数字+1
# django中使用事务
1 导入
from django.db import transaction
2 使用上下文管理器使用
with transaction.atomic():
写的代码,会要么都成功
要么都失败
https://www.cnblogs.com/lisixian/
#1 前端使用bootstrap的列表组
<div>
<span id="id_commit_text">评论列表
</span>
</div>
<ul class="list-group">
{% for commit in commit_list %}
<li class="list-group-item">
<div>
<span><a href=""># {{ forloop.counter }} 楼</a></span>
<span>{{ commit.create_time|date:"Y-m-d H:i" }}</span>
<span><a href="/{{ commit.user.username }}">{{ commit.user.username }}</a></span>
</div>
<div style="padding: 10px">
{# 判断 parent_id是否为空,如果为空,就是下面,如果不为空,找到父评论人名 @#}
{% if commit.parent_id %}
<a href="/{{ commit.parent_id.user.username }}">@ {{ commit.parent_id.user.username }}</a>
{% endif %}
<br>
{{ commit.content }}
</div>
</li>
{% endfor %}
</ul>
</div>
def article_detail(request, username, article_id):
article = Article.objects.filter(pk=article_id).first()
commit_list=Commit.objects.filter(article_id=article.id)
return render(request, 'article_detail.html', locals())
$("#btn_commit").click(function () {
// 谁给哪篇文章 评论了什么内容---》必须登录
var content = $("#id_text").val()
if (content) {
$.ajax({
url: '/commit/',
method: 'post',
data: {
article_id: '{{ article.id }}',
content: content,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data) {
console.log(data)
if (data.code == 100) {
// 把 字符串标签,拼接在后面 es6 模板字符串语法--》类似于python的 'asdfas%sasdf%d'
var html_content = `
<li class="list-group-item">
<p><span class="fa fa-address-card-o">${data.username}:</span></p>
<p>${data.content}</p>
</ul>
`
$('.list-group').append(html_content)
}
}
})
} else {
$('#alert_error').removeClass('hidden')
}
})
def commit(request):
user = request.user
if user.is_authenticated:
article_id = request.POST.get('article_id')
content = request.POST.get('content')
with transaction.atomic():
commit = Commit.objects.create(user=user, article_id=article_id, content=content)
# 评论数 +1
Article.objects.filter(pk=article_id).update(commit_number=F('commit_number') + 1)
return JsonResponse({'code': '100', 'msg': '评论成功', 'content': commit.content,'username':user.username})
else:
return JsonResponse({'code': '101', 'msg': '没有登录'})
## html中:
<div class="pull-right">
<span style="margin-left: 10px;margin-right: 10px" class="replay"
username="{{ commit.user.username }}" commit_id="{{ commit.id }}"><a>回复</a></span>
<span>删除</span>
</div>
## js中:给回复绑定事件
var parent_id=null
$('.replay').click(function () {
var username = "@" + $(this).attr('username') + '\n'
$("#id_text").val(username)
parent_id = $(this).attr('commit_id')
})
## 评论提交
$("#btn_commit").click(function () {
var content = $("#id_text").val()
if (parent_id) {
var i = content.indexOf('\n') // 找到 \n在字符串中得位置 4
content = content.substring(i + 1) // 把字符串截断,只要 \n往后额
console.log(content);
}
if (content) {
$.ajax({
url: '/commit/',
method: 'post',
data: {
parent_id: parent_id,
article_id: '{{ article.id }}',
content: content,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data) {
console.log(data)
if (data.code == 100) {
$("#id_text").val('') // 清空输入框内容
var html_content = `
<li class="list-group-item">
<p><span class="fa fa-address-card-o">${data.username}:</span></p>
<p>${data.content}</p>
</ul>
`
$('.list-group').append(html_content)
} else if (data.code == 103) {
$("#id_text").val('') // 清空输入框内容
var html_content = `
<li class="list-group-item">
<p><span class="fa fa-address-card-o">${data.username}:</span></p>
<p>@${data.parent_name}</p>
<p>${data.content}</p>
</ul>
`
$('.list-group').append(html_content)
}
}
})
} else {
$('#alert_error').removeClass('hidden')
}
})
def commit(request):
user = request.user
if user.is_authenticated:
article_id = request.POST.get('article_id')
content = request.POST.get('content')
parent_id = request.POST.get('parent_id')
with transaction.atomic():
commit = Commit.objects.create(user=user, article_id=article_id, content=content, parent_id_id=parent_id)
# 评论数 +1
Article.objects.filter(pk=article_id).update(commit_number=F('commit_number') + 1)
if commit.parent_id:
return JsonResponse({'code': '103', 'msg': '评论成功', 'content': commit.content, 'username': user.username,
'parent_name': commit.parent_id.user.username})
else:
return JsonResponse(
{'code': '100', 'msg': '评论成功', 'content': commit.content, 'username': user.username})
else:
return JsonResponse({'code': '101', 'msg': '没有登录'})
@login_required(login_url='/login/')
def backend(request):
article_list = Article.objects.filter(blog=request.user.blog)
return render(request, 'backend/backend_index.html', locals())
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>后台管理</title>
<script src="/static/js/jquery.min.js"></script>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid navbar-inverse">
<div class="navbar-header ">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">后台管理</a>
</div>
</div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
<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">
<ul class="nav nav-pills nav-stacked nav-pills-stacked-example">
<li role="presentation"><a href="#">新建文章</a></li>
<hr>
<li role="presentation"><a href="#">修改头像</a></li>
<hr>
<li role="presentation"><a href="#">草稿箱</a></li>
</ul>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingTwo">
<h4 class="panel-title">
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion"
href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
分类
</a>
</h4>
</div>
<div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">
<div class="panel-body">
<ul class="nav nav-pills nav-stacked nav-pills-stacked-example">
<li role="presentation"><a href="#">分类一</a></li>
<hr>
<li role="presentation"><a href="#">分类二</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-9">
<div class="bs-example bs-example-tabs" data-example-id="togglable-tabs">
<ul id="myTabs" class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#home" id="home-tab" role="tab" data-toggle="tab"
aria-controls="home" aria-expanded="true">文章</a></li>
<li role="presentation" class=""><a href="#profile" role="tab" id="profile-tab" data-toggle="tab"
aria-controls="profile" aria-expanded="false">随笔</a></li>
<li role="presentation" class="dropdown">
<a href="#" id="myTabDrop1" class="dropdown-toggle" data-toggle="dropdown"
aria-controls="myTabDrop1-contents" aria-expanded="false">更多 <span
class="caret"></span></a>
<ul class="dropdown-menu" aria-labelledby="myTabDrop1" id="myTabDrop1-contents">
<li><a href="#dropdown1" role="tab" id="dropdown1-tab" data-toggle="tab"
aria-controls="dropdown1">相册</a></li>
<li><a href="#dropdown2" role="tab" id="dropdown2-tab" data-toggle="tab"
aria-controls="dropdown2">测试</a></li>
</ul>
</li>
</ul>
<div id="myTabContent" class="tab-content">
<div role="tabpanel" class="tab-pane fade active in" id="home" aria-labelledby="home-tab">
{% block articles %}
{% endblock %}
</div>
<div role="tabpanel" class="tab-pane fade" id="profile" aria-labelledby="profile-tab">
随笔
</div>
<div role="tabpanel" class="tab-pane fade" id="dropdown1" aria-labelledby="dropdown1-tab">
相册
</div>
<div role="tabpanel" class="tab-pane fade" id="dropdown2" aria-labelledby="dropdown2-tab">
更多
</div>
</div>
</div>
</div>
</div>
</div>
</body>
{% block script %}
{% endblock %}
</html>
{% extends 'backend/backend_base.html' %}
{% block articles %}
<div>
<table class="table table-striped">
<thead>
<tr>
<th>文章id</th>
<th>文章名字</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for article in article_list %}
<tr>
<th scope="row">{{ article.id }}</th>
<td><a href="/{{ request.user.username }}/articles/{{ article.id }}.html">{{ article.title }}</a>
</td>
<td>{{ article.create_time|date:"Y年m月d日" }}</td>
<td><a href="">编辑</a> | <a href="/delete/{{ article.id }}">删除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
<a href="/delete/{{ article.id }}">删除</a>
@login_required(login_url='/login/')
def delete_article(request, pk):
Article.objects.filter(pk=pk).delete()
return redirect('/backend/')
@login_required(login_url='/login/')
def add_article(request):
if request.method == 'GET':
# 当前作者所有分类
category_list = Category.objects.filter(blog=request.user.blog).all()
tag_list = Tag.objects.filter(blog=request.user.blog).all()
return render(request, 'backend/add_article.html', locals())
else:
title = request.POST.get('title')
content = request.POST.get('content')
category = request.POST.get('category')
desc = content[0:70]
tag = request.POST.getlist('tag')
article = Article.objects.create(title=title, desc=desc, content=content, category_id=category,
blog=request.user.blog)
# 中间表如果自动生成,有如下方式操作中间表
article.tag.add(*tag) # id 或对象 都可以 article.tag.add(1,2)
# article.tag.clear()
# article.tag.set()
# article.tag.remove()
return redirect('/backend/')
{% extends 'backend/backend_base.html' %}
{% block articles %}
<div>
<h3 class="text-center">添加文章</h3>
<form method="post">
{% csrf_token %}
<div class="form-group">
<label for="">标题</label>
<input type="text" class="form-control" name="title">
</div>
<div class="form-group">
<label for="">内容</label>
<textarea name="content" id="" cols="200" rows="10" class="form-control"></textarea>
</div>
<div class="form-group">
<label for="">分类</label>
<select class="form-control" name="category">
{% for category in category_list %}
<option value="{{ category.id }}">{{ category.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="">标签</label>
<select class="form-control" multiple name="tag">
{% for tag in tag_list %}
<option value="{{ tag.id }}">{{ tag.name }}</option>
{% endfor %}
</select>
</div>
<div class="text-center">
<button class="btn btn-danger">新增文章</button>
</div>
</form>
</div>
{% endblock %}
浙公网安备 33010602011771号