好好吃饭 按时睡觉 不要抱怨 心怀善念 坚持做自己喜欢做的事 用心感受生活的每一个细节 沉淀 再沉淀 因为你要成为一个温柔而强大的人
一、需求分析,数据库表设计
需求分析:
1、登录注册功能;
2、首页;
3、分别展示出书籍页面,作者页面,出版社页面;
4、书籍页面功能有添加书本、编辑、删除;
5、作者页面功能有添加作者、编辑、删除、作者详情;
6、出版社页面功能有添加出版社、编辑、删除
数据库表设计
一共五张表
用户表 User: name | password | register_time
图书表 Book: title | price | publish_time | publish|author
(ps:publish和authors是外键字段)
出版社表 Publish: name | addr | email
作者表 Author: name | age | authordetail
作者详情表 AuthorDetail: phone | addr
一个出版社可以出版多本书籍,但一本书只能在一个出版社出版(一对多)
一个作者可以写多本书,一本书也可有多个作者(多对多)
一个作者对应一个详情信息(一对一)
二、Django环境配置
⚠️还要在项目或应用的init文件中写入下面代码,告诉Django使用的是mysql数据库:
import pymysql
pymysql.install_as_MySQLdb()
三、图书管理系统的登录、注册
1、路由配置(urls.py)
url(r'^$', views.login,name='login'), # 精确定位路由,默认打开就是登录界面
url(r'^register/', views.register,name='register'),
2、前端页面
🌸 登录界面(login.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
<script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="panel panel-primary">
<div class="panel-heading" style="background-color: lightskyblue">
<h3 class="panel-title text-center">欢迎登录图书管理系统</h3>
</div>
<div class="panel-body">
<div class="text-center">
<form action="" method="post">
<p>姓名:
<input type="text" name="name" >
</p>
<p>密码:
<input type="text" name="password">
</p>
<input type="submit" value="登录" class="btn btn-info" name="login" style="display: block;float: left;margin-left: 450px">
</form>
<a href="{% url 'register' %}" style="display: block;">
<button class="btn btn-danger" style="margin-left: -390px">注册</button>
</a>
</div>
</div>
</div>
</div>
</body>
</html>
🌸注册界面(register.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
<script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="panel panel-primary">
<div class="panel-heading" style="background-color: #bce8f1">
<h3 class="panel-title text-center">用户注册</h3>
</div>
<div class="panel-body">
<div>
<form action="" method="post">
<div class="form-group has-success">
<label class="control-label" for="inputSuccess1">用户名</label>
<input type="text" class="form-control" id="inputSuccess1" aria-describedby="helpBlock2"
name="name">
</div>
<div class="form-group has-warning">
<label class="control-label" for="inputWarning1">密码</label>
<input type="text" class="form-control" id="inputWarning1">
</div>
<div class="form-group has-error">
<label class="control-label" for="inputError1">确认密码</label>
<input type="text" class="form-control" id="inputError1" name="password">
</div>
<input type="submit" class="btn btn-success" style="display: block;float: left;margin-left: 450px">
</form>
<a href="{% url 'login' %}">
<button type="submit" class="btn btn-warning" style="margin-left: 10px">返回</button>
</a>
</div>
</div>
</div>
</div>
</body>
</html>
3、后端逻辑(views.py)
'''
登录功能逻辑思路:
从前端获取姓名和密码;
判断姓名和密码是否为空;
从数据库的user表中查出用户姓名和密码;
循环列表得到用户对象;
将用户名和密码与前端得到的名字和密码进行比对;
如果比对成功则登录成功跳转到home页面;
如果比对不成功则返回一个登录失败页面,显示返回注册
'''
def login(request):
if request.method == 'POST':
name = request.POST.get('name')
password = request.POST.get('password')
if name and password:
user_list=models.User.objects.values('name','password')
for user in user_list:
if name==user.get('name'):
if password==user.get('password'):
return redirect(reverse('home'))
else:
return HttpResponse('密码错啦!')
else:
return HttpResponse('请输入用户名和密码!')
return render(request, 'login.html', locals())
'''
注册功能逻辑:
从前端获取姓名和密码;
判断姓名和密码是否为空;
从数据库的user表中查出用户姓名;
for循环出用户姓名对象;
判断前端输入的名字是否在用户姓名对象里的名字中;
如果名字存在则发出提示信息;
如果不存在则进入创建姓名和密码到数据库中;
创建完成跳转到登录界面;
'''
def register(request):
if request.method == 'POST':
name = request.POST.get('name')
password = request.POST.get('password')
if name and password:
username_list = models.User.objects.values('name')
for username in username_list:
if name in username.get('name'):
return HttpResponse('用户已存在,请直接登录!')
else:
models.User.objects.create(name=name, password=password)
else:
return HttpResponse('请输入用户名和密码!')
return redirect(reverse('login'))
return render(request, 'register.html')
四、home主页面搭建
1、路由配置(urls.py)
这里主要是给他一个反向解析的名字,无论前端url名字怎么变化,后端都能匹配到这个路由,而且在不同的视图函数中都能使用这个名字来定位到要解析的路由对应的视图函数。
url(r'^home/', views.home,name='home'),
2、前端页面(home.html)
首先要导入bootstrap样式,在里面找自己想要的样式拷贝过来修改。bootstrap样式传送门:https://v3.bootcss.com/
主页面应用的逻辑很少,主要是页面的搭建和数据的渲染。
<body>
{#导航条开始#}
<nav class="navbar navbar-btn bg-info">
<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 bg-info" href="#">图书管理系统</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">图书分类<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">推理小说</a></li>
<li><a href="#">经典名著</a></li>
<li><a href="#">悬疑小说</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">杂文</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">诗集</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">搜索</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">注销</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-3">
<div class="list-group">
<!--这里要对路由进行反向解析-->
<a href="{% url 'home' %}" class="list-group-item list-group-item-success">首页</a>
<a href="{% url 'book_list' %}" class="list-group-item list-group-item-info">图书列表</a>
<a href="{% url 'author_list' %}" class="list-group-item list-group-item-warning">作者列表</a>
<a href="{% url 'publish_list' %}" class="list-group-item list-group-item-danger">出版社列表</a>
</div>
<ul class="list-group">
<li class="list-group-item list-group-item-success">咸鱼今天努力了没</li>
<li class="list-group-item list-group-item-info">咸鱼今天努力了吗</li>
<li class="list-group-item list-group-item-warning">咸鱼今天要努力呀</li>
<li class="list-group-item list-group-item-danger">咸鱼加油</li>
</ul>
</div>
{#左边栏结束#}
{# 右边栏开始#}
<div class="col-md-9">
<div class="panel panel-primary">
<div class="panel-heading" style="background-color: lightskyblue">
<h3 class="panel-title">图书管理系统</h3>
</div>
<div class="panel-body">
<!--划分变动区域-->
{% block content %}
<div class="jumbotron" style="background-color: #bce8f1">
<h1>咸鱼今天努力了没?</h1>
<p>多读书多看报,少吃零食多睡觉</p>
</div>
{% endblock %}
</div>
</div>
</div>
{# 右边栏开始#}
</div>
</div>
</body>
3、后端逻辑(views.py)
对位填充,返回到主页面
def home(request):
return render(request, 'home.html')
五、图书列表页面,作者列表页面,出版社页面搭建
1、路由配置(urls.py)
url(r'^book_list/', views.book_list,name='book_list'),
url(r'^author_list/', views.author_list,name='author_list'),
url(r'^publish_list/', views.publish_list,name='publish_list'),
2、后端逻辑(views.py)
因为要先从数据库中查询出所有信息,然后渲染到前端页面,所以先写逻辑。
这里查询出来的是个queryset对象,是个列表,对象还能继续点他的属性,这里显示名字是因为在模型表中用_ str_自定义print,在模型层加入了如下代码def __str__(self): return '作者对象的名字:%s'%self.name
,下面的🌰是查询所有作者信息,查询出来是作者的QuerySet 对象:
<QuerySet [<Author: 作者对象的名字:太宰治>, <Author: 作者对象的名字:东野圭吾>, <Author: 作者对象的名字:余华>, <Author: 作者对象的名字:王小波>, <Author: 作者对象的名字:wpr>, <Author: 作者对象的名字:万佩佩>]>
# 书籍列表
def book_list(request):
# 先查询出所有书籍信息,将内容渲染到前端
book_list = models.Book.objects.all()
return render(request, 'book_list.html', locals())
# 作者列表
def author_list(request):
# 查询出所有作者信息,将内容渲染到前端
author_list = models.Author.objects.all()
return render(request, 'author_list.html', locals())
# 出版社列表
def publish_list(request):
# 查询出所有出版社信息,将内容渲染到前端
publish_list = models.Publish.objects.all()
return render(request, 'publish_list.html', locals())
3、前端页面(book_list.html,author_list.html,publish_list.html)
🌸 book_list.html
<!--继承主页-->
{% extends 'home.html' %}
<!--在主页变动区域内写内容-->
{% block content %}
<a href="{% url 'book_add' %}" class="btn bg-info">添加书籍 </a>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th style="text-align: center">id</th>
<th style="text-align: center">title</th>
<th style="text-align: center">price</th>
<th style="text-align: center">publish</th>
<th style="text-align: center">publish_time</th>
<th style="text-align: center">authors</th>
<th style="text-align: center">actions</th>
</tr>
</thead>
<tbody>
<!--从书籍列表中循环出书的对象-->
{% for book in book_list %}
<tr>
<td>{{ book.pk }}</td>
<td>{{ book.title }}</td>
<td>{{ book.price }}</td>
<td>{{ book.publish.name }}</td>
<!--过滤器给时间设置格式-->
<td>{{ book.publish_time|date:'Y-m-d' }}</td>
<td>
<!--⚠️因为书籍中作者是作为外键字段,所以从书籍表中正向查询出所有作者,for循环出作者对象-->
{% for author_obj in book.authors.all %}
<!--⚠️如果不是最后一个值,就在后面加、隔开,如果是最后一个值,forloop.last置为True,结尾就不加管道符-->
{% if forloop.last %}
{{ author_obj.name }}
{% else %}
{{ author_obj.name }}、
{% endif %}
{% endfor %}
</td>
<td style="text-align: center">
<!--⚠️使用无名分组反向解析到编辑和删除书籍的路由,将book的id作为参数传递,这样就能知道编辑和删除的具体是哪个,绑定一一对应的关系-->
<a href="{% url 'book_edit' book.pk %}" class="btn bg-success btn-sm" >编辑</a>
<a href="{% url 'book_delete' book.pk %}" class="btn bg-danger btn-sm">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
🐷:在每个 {% for %}循环里有一个称为 forloop的模板变量,这个变量有一些提示循环进度信息的属性。
🐟forloop.counter 是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。
🐟forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
🐟forloop.revcounter 是表示循环中剩余项的整型变量。 在循环初次执行时 forloop.revcounter 将被设置为序列中项的总数。 最后一次循环执行中,这个变量将被置1。
🐟forloop.revcounter0 类似于 forloop.revcounter ,但它以0做为结束索引。在第一次执行循环时,该变量会被置为序列的项的个数减1。
🐟forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为True,需要特殊处理第一个元素时很方便:
{% for object in objects %}
{% if forloop.first %}
<li class="first">
{% else %}
<li>
{% endif %}
{{ object }}
</li>
{% endfor %}
🐟forloop.last 是一个布尔值;在最后一次执行循环时被置为True。 一个常见的用法是在一系列的链接之间放置管道符(|)
{% for link in links %}
{{ link }}{% if not forloop.last %} | {% endif %}
{% endfor %}
输出结果是:Link1 | Link2 | Link3 | Link4
另一个常见的用途是为列表的每个单词的加上逗号。
<p>Favorite places:</p>
{% for p in places %}
{{ p }}{% if not forloop.last %}, {% endif %}
{% endfor %}
输出结果是:厦门,广州,上海
🐟forloop.parentloop 在嵌套的循环中, forloop.parentloop引用父级循环的 forloop 对象。举个🌰:
{% for country in countries %}
<table>
{% for city in country.city_list %}
<tr>
<!--循环的是父级country对象的次数-->
<td>Country #{{ forloop.parentloop.counter }}</td>
<td>City #{{ forloop.counter }}</td>
<td>{{ city }}</td>
</tr>
{% endfor %}
</table>
{% endfor %}
⚠️forloop 变量只在循环内部可用。模板解析器遇到 {% endfor %} 时, forloop 随之消失,不可访问了。
⚠️Context和forloop变量
在一个 {% for %} 块中,已存在的变量会被移除,以避免 forloop 变量被覆盖。 Django会把这个变量移动到 forloop.parentloop 中。通常我们不用担心这个问题,但是一旦我们在模板中定义了 forloop 这个变量(当然我们反对这样做),在 {% for %} 块中它会在 forloop.parentloop 被重新命名。
🌸author_list.html
<!--继承主页-->
{% extends 'home.html' %}
<!--修改分块内容-->
{% block content %}
<a href="{% url 'author_add' %}" class="btn bg-danger">添加作者 </a>
<table class="table table-striped table-bordered table-hover text-center">
<thead>
<tr>
<th style="text-align: center">id</th>
<th style="text-align: center">name</th>
<th style="text-align: center">age</th>
<th style="text-align: center">authordetail</th>
<th style="text-align: center">action</th>
</tr>
</thead>
<tbody>
{% for author in author_list %}
<tr>
<td>{{ author.pk }}</td>
<td>{{ author.name }}</td>
<td>{{ author.age }}</td>
<td>
<a href="{% url 'author_detail' author.pk %}" class="btn bg-success btn-sm">作者信息</a>
</td>
<td>
<a href="{% url 'author_edit' author.pk %}" class="btn bg-info btn-sm">编辑</a>
<a href="{% url 'author_delete' author.pk %}" class="btn bg-danger btn-sm">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
🌸 publish_list.html
<!--继承主页-->
{% extends 'home.html' %}
<!--编辑分块内容-->
{% block content %}
<a href="{% url 'publish_add' %}" class="btn bg-warning">添加出版社 </a>
<table class="table table-striped table-bordered table-hover text-center">
<thead >
<tr>
<th style="text-align: center">id</th>
<th style="text-align: center">name</th>
<th style="text-align: center">addr</th>
<th style="text-align: center">email</th>
<th style="text-align: center">action</th>
</tr>
</thead>
<tbody>
{% for publish in publish_list %}
<tr>
<td>{{ publish.pk }}</td>
<td>{{ publish.name }}</td>
<td>{{ publish.addr }}</td>
<td>{{ publish.email }}</td>
<td>
<a href="{% url 'publish_edit' publish.pk %}" class="btn bg-info btn-sm">编辑</a>
<a href="{% url 'publish_delete' publish.pk %}" class="btn bg-danger btn-sm">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
六、图书页面之添加书籍
1、路由配置(urls.py)
url(r'^add_book/', views.add_book,name='book_add'),
2、 前端页面(add_book.html)
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">添加书籍</h1>
<form action="" method="post">
<p>title:
<input type="text" class="form-control" name="title">
</p>
<p>price:
<input type="text" class="form-control" name="price">
</p>
<p>publish_date:
<input type="date" class="form-control" name="date">
</p>
<p>publish:
<select name="publish" id="" class="form-control">
<!--对后端查询到的出版社列表for循环,取出出版社对象-->
{% for publish in publish_list %}
<!--单选下拉框里显示的是出版社id对应的出版社名,value是后端接收到的publish对象的id-->
<option value="{{ publish.pk }}">{{ publish.name }}</option>
{% endfor %}
</select>
</p>
<p>authors:
<!--多选下拉框里显示的是作者id对应的作者名,value是后端接收到的author对象的id-->
<!--⚠️这里将单选下拉框变成多选下拉框用multiple-->
<select name="authors" id="" class="form-control" multiple>
{% for author in author_list %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endfor %}
</select>
</p>
<input type="submit" class="btn bg-warning pull-right">
</form>
{% endblock %}
3、后端逻辑(views.py)
def add_book(request):
if request.method == 'POST':
title = request.POST.get('title')
price = request.POST.get('price')
# publish拿到的是publish的id
publish_id = request.POST.get('publish')
publish_date = request.POST.get('date')
authors = request.POST.getlist('authors') # [1,2,3]
# 数据库新增数据,⚠️book表中的只有publish,但是他是外键字段foreignkey,会自动增加_id变成publish_id,因此更新的时候这里还是要写publish_id
book_obj = models.Book.objects.create(title=title, price=price, publish_id=publish_id,
publish_time=publish_date)
# authors是多对多字段,去到书籍与作者的第三张表手动创建关系,因为authors拿出来是个列表,所以将它打散添加
book_obj.authors.add(*authors)
# 跳转到图书的展示页面
return redirect(reverse('book_list'))
# 将出版社和作者数据全部传递给添加页面
publish_list = models.Publish.objects.all()
author_list = models.Author.objects.all()
# get请求返回一个添加页面
return render(request, 'add_book.html', locals())
七、图书页面之编辑书籍
1、路由配置(urls.py)
url(r'^edit_book/(\d+)', views.edit_book,name='book_edit'),
2、 前端页面(edit_book.html)
编辑书籍之前,要把原信息都展示出来
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">编辑书籍</h1>
<form action="" method="post">
<!--input框内value展示出来的是原信息,是从后端传来的对象点属性-->
<p>title:
<input type="text" class="form-control" name="title" value="{{ edit_obj.title }}">
</p>
<p>price:
<input type="text" class="form-control" name="price" value="{{ edit_obj.price }}">
</p>
<p>publish_date:
<input type="date" class="form-control" name="date" value="{{ edit_obj.publish_time|date:'Y-m-d' }}">
</p>
<p>publish:
<select name="publish" id="" class="form-control">
<!--⚠️ 先for循环出所有出版社名;
如果要编辑对象的出版社名和上面循环出的出版社名相同,则高亮显示(selected表示选中)出版社的名字;
ps:value是后端要接收的对应出版社的id
-->
{% for publish in publish_list %}
{% if edit_obj.publish == publish %}
<option value="{{ publish.pk }}" selected>{{ publish.name }}</option>
{% else %}
<option value="{{ publish.pk }}">{{ publish.name }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<p>authors:
<select name="authors" id="" class="form-control" multiple>
<!--⚠️ 先for循环出所有作者;
如果该作者在要编辑对象的所有作者中,则高亮显示(selected表示选中)作者的名字;
ps:value是后端要接收的对应出版社的id
-->
{% for author in author_list %}
{% if author in edit_obj.authors.all %}
<option value="{{ author.pk }}" selected>{{ author.name }}</option>
{% else %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<input type="submit" class="btn bg-success pull-right">
</form>
{% endblock %}
3、后端逻辑(views.py)
def edit_book(request, edit_id):
# 获取要编辑的对象
edit_obj = models.Book.objects.filter(pk=edit_id).first()
if request.method == 'POST':
title = request.POST.get('title')
price = request.POST.get('price')
publish_date = request.POST.get('date')
publish_id = request.POST.get('publish')
# 因为一本书的作者不止一个,所以要用getlist取值
authors = request.POST.getlist('authors')
# 根据要编辑的id更新数据库中的信息
models.Book.objects.filter(pk=edit_id).update(title=title, price=price, publish_time=publish_date,
publish_id=publish_id)
# 更新作者,set里面要放可迭代对象
edit_obj.authors.set(authors)
return redirect(reverse('book_list'))
publish_list = models.Publish.objects.all()
author_list = models.Author.objects.all()
return render(request, 'edit_book.html', locals())
八、图书页面之删除书籍
1、路由配置(urls.py)
url(r'^delete_book/(\d+)', views.delete_book,name='book_delete'),
2、 后端逻辑(views.py)
因为删除书籍只要直接删除就好了,没有页面展示。
def delete_book(request, delete_id):
# 根据要删除对象的id来删除对应的书籍
models.Book.objects.filter(pk=delete_id).delete()
return redirect(reverse('book_list'))
九、作者页面之添加作者
1、路由配置(urls.py)
url(r'^add_author/', views.add_author,name='author_add'),
2、 前端页面(add_author.html)
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">添加作者</h1>
<form action="" method="post">
<p>name:
<input type="text" class="form-control" name="name">
</p>
<p>age:
<input type="text" class="form-control" name="age">
</p>
<p>phone:
<input type="text" class="form-control" name="phone">
</p>
<span>addr:
<select name="" id="a1"></select>
<select name="addr" id="a2"></select>
</span>
<!--⚠️ 这里使用js实现省市联动-->
<script>
let proEle=document.getElementById('a1');
let cityEle=document.getElementById('a2');
let data={"江苏省": ["苏州", "南京","常州","无锡"], "北京市": ["朝阳区", "海淀区"], "上海市": ["静安区", "闵行区"],"其他":["东京","巴黎","土星","木星"]};
// 将所有的省渲染到proEle标签内部,for循环获取所有的省
for (let pro in data){
// 创建option标签
let opEle=document.createElement('option');
// 给option标签设置文本值
opEle.innerText=pro;
// 将生成的option添加到proEle中
proEle.appendChild(opEle)
}
proEle.onchange=function () {
// 先清空cityEle标签内所有内容
cityEle.innerHTML='';
// 获取用户选择的省,根据省拿到对应的市
let choice_pro=proEle.value;
let cityList=data[choice_pro];
// for循环创建option标签添加到cityEle标签内
for(let i=0;i<cityList.length;i++){
// 创建option标签并添加文本
let cEle=document.createElement('option');
//给option标签设置文本值
cEle.innerText=cityList[I]
// 将生成的option添加到proEle中
cityEle.appendChild(cEle)
}
}
</script>
<input type="submit" class="btn bg-success pull-right">
</form>
{% endblock %}
3、后端逻辑(views.py)
def add_author(request):
if request.method == 'POST':
name = request.POST.get('name')
age = request.POST.get('age')
phone = request.POST.get('phone')
addr = request.POST.get('addr')
# 新增作者,与之一对一关系的作者详情表也要新增信息
# 首先新增作者详情表中的数据,赋值给作者详情对象
authordetail_obj = models.AuthorDetail.objects.create(phone=phone, addr=addr)
# 因为是一对一的关系,所以在作者表中新增数据时,作者详情这个外键是和作者详情对象的主键绑定的
models.Author.objects.create(name=name, age=age, authordetail_id=authordetail_obj.pk)
return redirect(reverse('author_list'))
return render(request, 'add_author.html', locals())
十、作者页面之编辑作者
1、路由配置(urls.py)
url(r'^edit_author/(\d+)', views.edit_author,name='author_edit'),
2、 前端页面(edit_author.html)
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">编辑作者信息</h1>
<form action="" method="post">
<p>name:
<input type="text" class="form-control" name="name" value="{{ edit_obj.name }}">
</p>
<p>age:
<input type="text" class="form-control" name="age" value="{{ edit_obj.age }}">
</p>
<input type="submit" class="btn bg-success pull-right">
</form>
{% endblock %}
3、后端逻辑(views.py)
def edit_author(request, edit_id):
# 先获取要编辑的对象
edit_obj = models.Author.objects.filter(pk=edit_id).first()
if request.method == 'POST':
name = request.POST.get('name')
age = request.POST.get('age')
models.Author.objects.filter(pk=edit_id).update(name=name, age=age)
return redirect(reverse('author_list'))
authordetail_list = models.AuthorDetail.objects.all()
return render(request, 'edit_author.html', locals())
十一、作者页面之作者详情
1、路由配置(urls.py)
url(r'^author_detail/(\d+)', views.author_detail,name='author_detail'),
2、 前端页面(author_detail.html)
这里是跳到另外一个页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
<script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="panel panel-info">
<!-- Default panel contents -->
<div class="panel-heading text-center" ><h1>作者信息</h1></div>
<div class="panel-body">
<table class="table table-striped table-bordered table-hover text-center">
<thead>
<tr>
<th style="text-align: center">id</th>
{# <th style="text-align: center">name</th>#}
<th style="text-align: center">phone</th>
<th style="text-align: center">addr</th>
</tr>
</thead>
<tbody>
{% for authordetail in authordetail_list %}
<tr>
<td>{{ authordetail.pk }}</td>
{# <td>{{ author_name }}</td>#}
<td>{{ authordetail.phone }}</td>
<td>{{ authordetail.addr }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="{% url 'author_list' %}" class="btn bg-success pull-right" >返回 </a>
</div>
</div>
</div>
</div>
</body>
</html>
3、后端逻辑(views.py)
def author_detail(request, detail_id):
author_obj = models.Author.objects.filter(pk=detail_id).first()
authordetail_list = models.AuthorDetail.objects.filter(pk=author_obj.authordetail_id).all()
return render(request, 'author_detail.html', locals())
十二、作者页面之删除作者
1、路由配置(urls.py)
url(r'^delete_author/(\d+)', views.delete_author,name='author_delete'),
2、后端逻辑(views.py)
def delete_author(request, delete_id):
models.Author.objects.filter(pk=delete_id).delete()
return redirect(reverse('author_list'))
十三、出版社页面之添加出版社
1、路由配置(urls.py)
url(r'^add_publish/', views.add_publish,name='publish_add'),
2、 前端页面(edit_publish.html)
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">编辑出版社</h1>
<form action="" method="post">
<p>name:
<input type="text" class="form-control" name="name" value="{{ edit_obj.name}}">
</p>
<p>addr:
<input type="text" class="form-control" name="addr" value="{{ edit_obj.addr }}">
</p>
<p>email:
<input type="text" class="form-control" name="email" value="{{ edit_obj.email }}">
</p>
<input type="submit" class="btn bg-success pull-right">
</form>
{% endblock %}
3、后端逻辑(views.py)
def add_publish(request):
if request.method == 'POST':
name = request.POST.get('name')
addr = request.POST.get('addr')
email = request.POST.get('email')
publish_obj = models.Publish.objects.create(name=name, addr=addr, email=email)
return redirect(reverse('publish_list'))
return render(request, 'add_publish.html', locals())
十四、出版社页面之编辑出版社
1、路由配置(urls.py)
url(r'^edit_publish/(\d+)', views.edit_publish,name='publish_edit'),
2、 前端页面(edit_book.html)
{% extends 'home.html' %}
{% block content %}
<h1 class="text-center">编辑书籍</h1>
<form action="" method="post">
<p>title:
<input type="text" class="form-control" name="title" value="{{ edit_obj.title }}">
</p>
<p>price:
<input type="text" class="form-control" name="price" value="{{ edit_obj.price }}">
</p>
<p>publish_date:
<input type="date" class="form-control" name="date" value="{{ edit_obj.publish_time|date:'Y-m-d' }}">
</p>
<p>publish:
<select name="publish" id="" class="form-control">
{% for publish in publish_list %}
{% if edit_obj.publish == publish %}
<option value="{{ publish.pk }}" selected>{{ publish.name }}</option>
{% else %}
<option value="{{ publish.pk }}">{{ publish.name }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<p>authors:
<select name="authors" id="" class="form-control" multiple>
{% for author in author_list %}
{% if author in edit_obj.authors.all %}
<option value="{{ author.pk }}" selected>{{ author.name }}</option>
{% else %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<input type="submit" class="btn bg-success pull-right">
</form>
{% endblock %}
3、后端逻辑(views.py)
def edit_publish(request, edit_id):
edit_obj = models.Publish.objects.filter(pk=edit_id).first()
if request.method == 'POST':
name = request.POST.get('name')
addr = request.POST.get('addr')
email = request.POST.get('email')
models.Publish.objects.filter(pk=edit_id).update(name=name, addr=addr, email=email)
return redirect(reverse('publish_list'))
return render(request, 'edit_publish.html', locals())
十五、出版社页面之删除出版社
1、路由配置(urls.py)
url(r'^delete_publish/(\d+)', views.delete_publish,name='publish_delete'),
2、后端逻辑(views.py)
def delete_publish(request, delete_id):
models.Publish.objects.filter(pk=delete_id).delete()
return redirect(reverse('publish_list'))