总路由层url
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 首页
url(r'^$', views.home, name='hm'),
# 图书展示页
url(r'^book_list/', views.book_list, name='bl'),
# 图书添加
url(r'^book_add/', views.book_add, name='badd'),
# 图书编辑功能
url(r'^book_update/(\d+)/', views.book_update, name='bu'),
# 图书删除功能
url(r'^book_delete/(?P<delete_id>\d+)', views.book_delete, name='bd')
# 使用ajax实现删除功能
url(r'^del_book',views.del_book)
]
首页
def home(request):
return render(request, 'home.html') # 返回一个页面
# home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.min.css">
{% block css %}
{% endblock %}
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<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="#">BMS</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">图书 <span class="sr-only">(current)</span></a></li>
<li><a href="#">作者</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">meng</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">更多 <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
<div class="list-group">
<a href="{% url 'hm' %}" class="list-group-item active">
首页
</a>
<a href="{% url 'bl' %}" class="list-group-item">图书列表</a>
<a href="#" class="list-group-item">出版社列表</a>
<a href="#" class="list-group-item">作者列表</a>
<a href="#" class="list-group-item">更多</a>
</div>
</div>
<div class="col-md-10">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">BMS</h3>
</div>
<div class="panel-body">
{% block content %}
<div class="jumbotron">
<h1>亚洲最大图书馆!</h1>
<p>应有尽有,经典图书</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">中外经典名著</a></p>
</div>
{% endblock %}
</div>
</div>
</div>
</div>
</div>
{% block js %}
{% endblock %}
</body>
</html>
图书展示页
# views.py
def book_list(request):
book_request = models.Book.objects.all()
return render(request, 'book_list.html', locals()) # 把所有的数据展示到页面
# book_list.html
{% extends 'home.html' %} # 用模板的继承
{% block css %}
<style>
.h2 {
color:darkorange;
}
</style>
{% endblock %}
{% block content %}
<h2 class="text-center h2" >精选推荐</h2>
<a href="{% url 'badd' %}" class="btn btn-success">添加书籍</a>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>主键</th>
<th>书名</th>
<th>价格</th>
<th>出版日期</th>
<th>出版社</th>
<th>作者</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for book_obj in book_request %}
<tr>
<td>{{ book_obj.id }}</td>
<td>{{ book_obj.title }}</td>
<td>{{ book_obj.price }}</td>
<td>{{ book_obj.publish_time|date:'Y-m-d' }}</td>
<td>{{ book_obj.publish.name }}</td>
{# <td>{{ book_obj.author.all }}</td>#}
<td>
{% for author_obj in book_obj.author.all %}
{% if forloop.last %}
{{ author_obj.name }}
{% else %}
{{ author_obj.name }},
{% endif %}
{% endfor %}
</td>
<td>
<a href="{% url 'bu' book_obj.pk %}" class="btn btn-primary btn-xs">编辑</a>
<a href="{% url 'bd' book_obj.pk %}" class="btn btn-danger btn-xs">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<nav aria-label="Page navigation" class="text-center">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
{% endblock %}
图书添加功能
# views.py
def book_add(request):
if request.method == 'POST':
# 获取用户上传的数据
title = request.POST.get('title')
price = request.POST.get('price')
publish_time = request.POST.get('publish_time')
publish_pk = request.POST.get('publish_pk')
author_pk = request.POST.getlist('author_pk')
# 向数据库添加数据
book_obj = models.Book.objects.create(title=title, price=price, publish_time=publish_time,publish_id=publish_pk)
book_obj.author.add(*author_pk) # author_pk:获取的是列表,用*打散一个个添加
return redirect('bl')
# 出版社对象
publish_request = models.Publish.objects.all()
# 作者对象
author_request = models.Author.objects.all()
return render(request, 'book_add.html', locals())
# book_add.html
{% extends 'home.html' %}
{% block content %}
<h2 class="text-center">图书添加</h2>
<form action="" method="post">
<p>书名:
<input type="text" name="title" class="form-control">
</p>
<p>价格:
<input type="text" name="price" class="form-control">
</p>
<p>出版日期:
<input type="date" name="publish_time" class="form-control">
</p>
<p>出版社:
<select name="publish_pk" id="" class="form-control">
// 循环出所有的出版社
{% for publish_obj in publish_request %}
<option value="{{ publish_obj.pk }}">{{ publish_obj.name }}</option>
{% endfor %}
</select>
</p>
<p>作者:
<select name="author_pk" id="" multiple class="form-control">
{% for author_obj in author_request %}
<option value="{{ author_obj.pk }}">{{ author_obj.name }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="添加书籍" class="btn btn-success btn-block">
</form>
{% endblock %}
图书编辑功能
# views.py
def book_update(request, update_id):
# 获取用户需要编辑的对象
update_obj = models.Book.objects.filter(pk=update_id).first()
if request.method == 'POST':
# 获取用户上传的数据
title = request.POST.get('title')
price = request.POST.get('price')
publish_time = request.POST.get('publish_time')
publish_pk = request.POST.get('publish_pk')
author_pk = request.POST.getlist('author_pk')
# 向数据库添加数据
models.Book.objects.filter(pk=update_id).update(title=title, price=price, publish_time=publish_time,publish_id=publish_pk)
# 修改第三方表
update_obj.author.set(author_pk)
# 也可以用对象点属性的方式修改,调用save保存
# update_obj.title = title
# update_obj.save()
return redirect('bl')
# 出版社对象
publish_request = models.Publish.objects.all()
# 作者对象
author_request = models.Author.objects.all()
# 返回一个编辑页面
return render(request, 'book_update.html',locals())
# book_update.html
{% extends 'home.html' %}
{% block content %}
<h2 class="text-center">图书修改</h2>
<form action="" method="post">
<p>书名:
<input type="text" name="title" class="form-control" value="{{ update_obj.title }}">
</p>
<p>价格:
<input type="text" name="price" class="form-control" value="{{ update_obj.price }}">
</p>
<p>出版日期:
<input type="date" name="publish_time" class="form-control" value="{{ update_obj.publish_time|date:'Y-m-d' }}">
</p>
<p>出版社:
<select name="publish_pk" id="" class="form-control">
{% for publish_obj in publish_request %} // 循环出所有的出版社
// 循环所有的出版社对象,跟书籍对象的出版社比对,如果一致则添加上selected默认值
{% if update_obj.publish == publish_obj %} // 判断循环的出版社是否和当前修改的出版社是否一样
<option value="{{ publish_obj.pk }}" selected>{{ publish_obj.name }}</option> // 一样的话,添加默认值
{% else %}
<option value="{{ publish_obj.pk }}">{{ publish_obj.name }}</option> // 否则,输出所有出版社
{% endif %}
{% endfor %}
</select>
</p>
<p>作者:
<select name="author_pk" id="" multiple class="form-control">
{% for author_obj in author_request %}
{% if author_obj in update_obj.author.all %}
<option value="{{ author_obj.pk }}" selected>{{ author_obj.name }}</option>
{% else %}
<option value="{{ author_obj.pk }}">{{ author_obj.name }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<input type="submit" value="修改书籍" class="btn btn-warning btn-block">
</form>
{% endblock %}
图书删除功能
# views.py
def book_delete(request,delete_id):
# 删除
models.Book.objects.filter(pk=delete_id).delete()
return redirect('bl') # 删除后重定向图书展示页面
使用Ajax实现二次确认删除功能
# 使用ajax就不能使用下面的url,会造成冲突
<a href="{% url 'bd' book_obj.pk %}" class="btn btn-danger btn-xs">删除</a> # 修改前
<a href="#" class="btn btn-danger btn-xs c1" delete_id="{{ book_obj.pk }}">删除</a> # 修改后
# // 标签既可以有默认的属性,也可以有自定义的属性,添加delete_id是可以获取主键id值
# views.py
def del_book(request):
# 判断当前请求是否为ajax请求
if request.is_ajax():
if request.method == 'POST': # 判断是否是ajax发来的post请求
# 拿到ajax传到后端的data值
delete_id = request.POST.get('delete_id')
# 根据传过来的主键id删除数据
models.Book.objects.filter(pk=delete_id).delete()
return HttpResponse('删除成功!')
# book_list.html
{% block js %}
<script>
var $btn = $('.c1'); // 找到c1标签
// 绑定点击事件
$btn.on('click',function () {
var delete_id = $(this).attr('delete_id'); // 拿当前点击按钮中的delete_id属性
var $this = $(this); // 给this设置一个变量
{#alert(delete_id); // 试验是否拿到主键id#}
// 做提醒效果
let res = confirm('确定删除吗');
// 判断是否为true
if (res){ //true
// 发送ajax请求
$.ajax({
url:'/del_book/', // 向它发送请求
type:'post',
data:{'delete_id':delete_id},
success:function (args) {
alert(args) ; // 接收到用户后端穿过来数据,代表已经删除成功
// 刷新页面
{#window.location.reload()#}
// js代码自动刷新
$this.parent().parent().remove()
}
})
}else { // false
return false
}
})
</script>
{% endblock %}
'''
总结:
1.先在a标签中添加一个自定义属性:delete_id={{book_obj.pk}},并且设置一个c1标签
2.找到c1标签,并且绑定一个点击事件
3.拿当前点击按钮中的delete_id属性
4.做提醒效果
5.判断是否为true
6.真的话:向后端发送ajax请求,并且其中把主键id传入到后端
7.在路由层和视图层开设出相应的函数
8.后端拿到ajax发来的主键id,根据主键id删除数据库数据,并给前端返回一个结果
9.前端拿到返回结果并打印,并刷新页面
'''
# 存在的问题:
window.location.reload()
当有多个页面时,使用上面的方法,会直接刷新到首页,会给用户造成不好的体验
# 解决:
可以根据js代码自动删除,通过代码把tr标签删除
var $this = $(this); // 给this设置一个变量
// js代码自动刷新
$this.parent().parent().remove()
试验url是否可以用反向解析
# 试验url是否可以用反向解析
<script>
var $btn = $('.c1');
$btn.on('click',function () {
$.ajax({
url:'{% url "bl" %}',
type: 'post',
data:'',
succees:function () {
}
})
})
</script>
[02/Dec/2021 16:58:16] "POST /del_book/ HTTP/1.1" 200 15 # 发送了一个post请求,证明是可以的
结合第三方模块实现二次确认删除功能
{% block js %}
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
<script>
var $btn = $('.c1'); // 找到c1标签
// 绑定点击事件
$btn.on('click',function (){
var delete_id = $(this).attr('delete_id'); // 拿当前点击按钮中的delete_id属性
var $this = $(this); // 给this设置一个变量
swal({
title: "确定要删除吗?",
text: "要想好哦!",
icon: "warning",
buttons: true,
dangerMode: true,
})
.then((willDelete) => {
if (willDelete) {
// 向后端发送ajax请求
$.ajax({
url:'/del_book/',
type:'post',
data:{'delete_id':delete_id},
success:function (args) {
// js代码自动刷新
$this.parent().parent().remove();
{#window.location.reload();#}
swal(args, {
icon: "success",
}
);
}
})
} else {
swal("取消成功!");
}
});
})
</script>
{% endblock %}
第三方模块:https://sweetalert.js.org