基础-图书管理系统

好好吃饭 按时睡觉 不要抱怨 心怀善念 坚持做自己喜欢做的事 用心感受生活的每一个细节 沉淀 再沉淀 因为你要成为一个温柔而强大的人

一、需求分析,数据库表设计

需求分析:
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环境配置

注册app

注释掉中间件,方便表单提交测试

连接数据库

⚠️还要在项目或应用的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'))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 前端相关 展示内容:浏览器接收后端返回的html文本(经过模板渲染)内容并在页面展示.与用户交互信息:js将用户产...
    Knight方阅读 2,842评论 0 1
  • 一、创建项目 1.1.创建项目和app django-admin startproject mysite-logi...
    鹏ve阅读 14,258评论 4 71
  • Django 准备 “虚拟环境为什么需要虚拟环境:到目前位置,我们所有的第三方包安装都是直接通过 pip inst...
    33jubi阅读 1,319评论 0 5
  • PythonWeb框架要点、Django介绍、工程搭建、配置、静态文件与路由 1.Python Web 框架要点 ...
    Cestine阅读 1,460评论 0 6
  • Django是一个用 Python 编写的 Web 框架。Web 框架是一种软件,基于web框架可以开发动态网站,...
    guanalex阅读 7,175评论 0 5