# 73. Django图书馆之作者的增删改查 - 多对多关系表
# 创建作者项目包( Author )
Django项目app --> 项目中又分了一级Python包,不同的功能放到不同的包里面
创建app
python manage.py startapp Author
告诉Django创建了一个app
在settings.py找那个的INSTALLED_APPS中添加新创建的app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'Press.apps.PressConfig',
'Book.apps.BookConfig',
]
# 创建作者需要的ORM配置
在models.py文件中
from django.db import models
# Create your models here.
from Book.models import Book_sql
class Author_sql(models.Model):
id = models.AutoField(primary_key=True) # 自增ID
name = models.CharField(max_length=16) # 作者名称
books = models.ManyToManyField(to=Book_sql) # 只是ORM层面建立的一个多对多关系,不是作者表的一个字段
写在models.py文件中,如果有关数据库操作的,比如,添加表、增加行、删除行、修改行等,都需要执行以下的步骤,让需要变更的操作,先记录在子项目的migrations目录中,在进行提交更改
生成记录命令:python3 manage.py makemigrations Author
提交变更记录修改命令:python3 manage.py migrate
# 业务逻辑代码
# 业务逻辑之查询
主要代码
## 后端函数代码
from django.shortcuts import render,redirect
from Author.models import Author_sql
from Book.models import Book_sql
# 查询
def author_subject(request):
author_user = Author_sql.objects.all() # 获取作者表的所有数据
book_user = Book_sql.objects.all() # 获取书籍表的所有数据
return render(request, "Author.html", {'author_user': author_user, 'book_user': book_user}) # 返回
# 业务逻辑之添加
主要代码
## 后端函数代码
from django.shortcuts import render,redirect
from Author.models import Author_sql
from Book.models import Book_sql
# 添加
def author_add(request):
name = request.POST.get("name") # 获取前端传递过来的POST类型,值为name的数据
select = request.POST.getlist("select") # 获取前端传递过来的POST类型,值为select的数据
add_obj = Author_sql.objects.create(name=name) # 把前端传递过来的数据增加到数据库中,创建作者
add_obj.books.add(*select) # 将新增的作者对应的书籍重设为前端传递过来的书籍ID,*代表批量
return redirect('/author/') # 返回
## 通过前端传来的数据,对数据进行插入
# 业务逻辑之删除
主要代码
## 后端函数代码
from django.shortcuts import render,redirect
from Author.models import Author_sql
from Book.models import Book_sql
# 删除
def author_del(request):
id = request.GET.get("id") # 获取前端传递过来的GET类型,值为id的数据
Author_sql.objects.filter(id=id).delete() # 删除前端传递过来的ID对应的数据库数据
return redirect('/author/') # 返回
# 业务逻辑之编辑
主要代码
## 后端函数代码
from django.shortcuts import render,redirect
from Author.models import Author_sql
from Book.models import Book_sqll
def author_edit(request):
id = request.POST.get("id") # 获取前端传递过来的GET类型,值为id的数据
name = request.POST.get("name") # 获取前端传递过来的GET类型,值为id的数据
book_id = request.POST.getlist("book_id") # 获取前端传递过来的GET类型,值为id的数据
edit_sql = Author_sql.objects.get(id=id) # 获取指定条件的数据库对象
edit_sql.name = name # 修改内存中对象的值
edit_sql.save() # 将内存中的对象值重新提交给数据库,如果值发生变化,数据库自动同步修改
edit_sql.books.set(book_id) # 修改作者和书的关系表
return redirect('/author/') # 返回
# 项目完整代码
# models.py文件
from django.db import models
# Create your models here.
from Book.models import Book_sql
class Author_sql(models.Model):
id = models.AutoField(primary_key=True) # 自增ID
name = models.CharField(max_length=16) # 作者名称
books = models.ManyToManyField(to=Book_sql) # 只是ORM层面建立的一个多对多关系,不是作者表的一个字段
# urls.py文件
from Press import views as prees
from Book import views as book
from Author import views as author
urlpatterns = [
# ---------> 出版社 <---------
url(r'^press/', prees.press_subject),
url(r'^press_add/', prees.press_add),
url(r'^press_del/', prees.press_del),
url(r'^press_edit/', prees.press_edit),
# ---------> 书籍 <---------
url(r'^book/', book.book_subject),
url(r'^book_add/', book.book_add),
url(r'^book_del/', book.book_del),
url(r'^book_edit/', book.book_edit),
# ---------> 作者 <---------
url(r'^author/', author.author_subject),
url(r'^author_add/', author.author_add),
url(r'^author_del/', author.author_del),
url(r'^author_edit/', author.author_edit),
]
# views.py文件
from django.shortcuts import render,redirect
from Author.models import Author_sql
from Book.models import Book_sql
# Create your views here.
# 查询
def author_subject(request):
author_user = Author_sql.objects.all() # 获取作者表的所有数据
book_user = Book_sql.objects.all() # 获取书籍表的所有数据
return render(request, "Author.html", {'author_user': author_user, 'book_user': book_user}) # 返回
# 添加
def author_add(request):
name = request.POST.get("name") # 获取前端传递过来的POST类型,值为name的数据
select = request.POST.getlist("select") # 获取前端传递过来的POST类型,值为select的数据
add_obj = Author_sql.objects.create(name=name) # 把前端传递过来的数据增加到数据库中,创建作者
add_obj.books.add(*select) # 将新增的作者对应的书籍重设为前端传递过来的书籍ID,*代表批量
return redirect('/author/') # 返回
# 删除
def author_del(request):
id = request.GET.get("id") # 获取前端传递过来的GET类型,值为id的数据
Author_sql.objects.filter(id=id).delete() # 删除前端传递过来的ID对应的数据库数据
return redirect('/author/') # 返回
# 编辑
def author_edit(request):
id = request.POST.get("id") # 获取前端传递过来的GET类型,值为id的数据
name = request.POST.get("name") # 获取前端传递过来的GET类型,值为id的数据
book_id = request.POST.getlist("book_id") # 获取前端传递过来的GET类型,值为id的数据
edit_sql = Author_sql.objects.get(id=id) # 获取指定条件的数据库对象
edit_sql.name = name # 修改内存中对象的值
edit_sql.save() # 将内存中的对象值重新提交给数据库,如果值发生变化,数据库自动同步修改
edit_sql.books.set(book_id) # 修改作者和书的关系表
return redirect('/author/') # 返回
# book.html文件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="content-Type" charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 描述网页,与之对应的属性值为content
<meta name="keywords" content="">
<meta name="description" content=""> -->
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/jquery-3.4.1.min.js"></script>
<style>
{# 显示的类 #}
.show {
display: block !important;
}
{# 不显示的类 #}
.hidden {
display: none !important;
}
.center {
text-align: center;
}
</style>
<title>作者</title>
</head>
<body>
<div class="container-fluid">
<div class="page-header">
<h1>作者</h1>
</div>
<div class="panel panel-default panel-primary">
<div class="panel-heading">作者操作界面</div>
<div class="panel-body">
<button type="button" class="btn btn-success Add_to pull-right" data-toggle="modal"
data-target=".bs-example-modal-sm"
data-target="#myModal" style="margin-right: 15px; margin-bottom: 15px">
添加作者
</button>
<table class="table table-striped table-hover table-bordered ">
<thead>
<tr>
<th class="center">序号</th>
<th class="center">作者</th>
<th class="center">书籍</th>
<th class="center">操作</th>
</tr>
</thead>
<tbody class="center">
{% for i in author_user %} {# 循环过滤从后端传递过来的数据 #}
<tr>
<td>{{ forloop.counter }}</td>
{# <td class="hidden"> {{ i.press.id }} </td>#}
{# 获取每行的ID,但让其不显示,为JS逻辑需要的代码 #}
<td class="hidden"> {{ i.id }} </td>
{# 获取每行的ID,但让其不显示,为后端逻辑需要的代码 #}
<td>{{ i.name }}</td>
<td>
{% for book in i.books.all %}
{% if forloop.last %}
《{{ book.name }}》
{% else %}
《{{ book.name }}》,
{% endif %}
{% empty %}
笔下暂无作品
{% endfor %}
</td>
{# 获取到的press字段数据是一个对象,关联表中对应的对象,可以直接通过对象拿到对应的数据 #}
<td>
<a class="btn btn-info book_edit" role="button">编辑</a>
<a href="/author_del/?id={{ i.id }}" class="btn btn-danger" role="button">删除</a>
{# 通过a标签的特点,让点击后,带ID的值返回给后端 #}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{# 添加作者开始 #}
<div class="modal Add_to_frame bs-example-modal-sm" tabindex="-1" role="dialog"
aria-labelledby="myLargeModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close Add_to_frame_Close1" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title">添加作者</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" action="/author_add/" method="post">
<div class="form-group">
<label class="col-sm-2 control-label">作者名称</label>
<div class="col-sm-10">
<input type="text" name="name" class="form-control">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">作者笔下书籍</label>
<div class="col-sm-10">
<select class="form-control" name="select" multiple="multiple">
{% for book_user in book_user %}
<option value="{{ book_user.id }}">{{ book_user.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default Add_to_frame_Close2" data-dismiss="modal">取消
</button>
<button type="submit" class="btn btn-primary">确定添加</button>
</div>
</form>
</div>
</div>
</div>
</div>
{# 添加书籍结束 #}
{# 编辑书籍开始 #}
<div class="modal edit_frame bs-example-modal-sm" tabindex="-1" role="dialog"
aria-labelledby="myLargeModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close edit_frame_Close1" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title">编辑作者</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" action="/author_edit/" method="post">
<div class="form-group">
<label class="col-sm-2 control-label">作者名称</label>
<div class="col-sm-10">
<input type="text" name="id" class="form-control edit_value_id hidden">
<input type="text" name="name" class="form-control edit_value_name">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">作者笔下书籍</label>
<div class="col-sm-10">
<select class="form-control edit_value_press" name="book_id" multiple="multiple">
{% for book_user in book_user %}
<option value="{{ book_user.id }}">{{ book_user.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default edit_frame_Close2" data-dismiss="modal">取消
</button>
<button type="submit" class="btn btn-primary">确定编辑</button>
</div>
</form>
</div>
</div>
</div>
</div>
{# 编辑书籍结束 #}
</body>
<script>
{# 添加框的点击开启事件 #}
$(".Add_to").click(function () {
$(".Add_to_frame").addClass("show");
});
{# 添加框的关闭事件 #}
$(".Add_to_frame_Close1").click(function () {
$(".Add_to_frame").removeClass("show");
});
$(".Add_to_frame_Close2").click(function () {
$(".Add_to_frame").removeClass("show");
});
{# 编辑框的点击开启事件 #}
$(".book_edit").click(function () {
$(".edit_frame").addClass("show");
var press_id = $(this).parent().prev().prev().prev().prev().text().trim();
{# 获取到当前点击行的 #}
var id = $(this).parent().prev().prev().prev().text();
{# 获取到当前点击行的数据库ID #}
var name = $(this).parent().prev().prev().text();
{# 获取到当前点击行的name值 #}
$(".edit_value_id").val(id);
{# 获取到的值,显示到所在的输入框中 但ID框不显示,为后端传递数据需要 #}
$(".edit_value_name").val(name);
{# 获取到的值,显示到所在的输入框中 #}
{#$("option[value='" + press_id + "']").prop("selected", true);#}
{# 认为select下拉列表的动态默认值 #}
});
{# 编辑框的关闭事件 #}
$(".edit_frame_Close2").click(function () {
$(".edit_frame").removeClass("show");
})
$(".edit_frame_Close1").click(function () {
$(".edit_frame").removeClass("show");
})
</script>
</html>