day9 图书设计项目

总路由层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">&laquo;</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">&raquo;</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

上一篇:聚合查询与分组查询


下一篇:如何开发一个npm包并发布