天天看点

Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

本案例主要演示Django的路由、视图函数、视图类、Orm、表单以及用户和权限。采用Django3+BootStrap技术栈。为了简化难度,仅仅使用了很少的JavaScript。全网不可多得得Django学习资料

简单的需求分析

Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

效果演示

Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

项目开发详细过程

使用Win10+PyCharm+Python3.8+Django3.1.5+SQLite+Navicat下开发。

项目及其应用的建立

E:\edu\Django从入门到项目实战>django-admin startproject mybook

Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

E:\edu\Django从入门到项目实战\mybook>python manage.py startapp app1

Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

准备工作

修改settings.py文件

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app1',
]           

配置静态文件、上传资源和登录url跳转

STATIC_URL = '/static/'
STATICFILES_DIRS=[os.path.join(BASE_DIR,'static')]

MEDIA_URL = '/media/'
MEDIA_ROOT=os.path.join(BASE_DIR,'media')


LOGIN_URL="/book/login/"           

修改mybook/urls.py文件

urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/',include("app1.urls")),
    re_path('media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}),
    re_path('static/(?P<path>.*)', serve, {"document_root": settings.STATIC_ROOT}),

           

模型建立

app1\models.py文件

from django.db import models




class Author(models.Model):
    a_id = models.AutoField(verbose_name='ID', primary_key=True)
    name = models.CharField(verbose_name='作者姓名', max_length=20)
    age = models.IntegerField(verbose_name='作者年龄', default=1)
    mobile = models.CharField(verbose_name='电话', max_length=11)
    address = models.CharField(verbose_name='地址', max_length=20)
    intro = models.TextField(verbose_name='简介', null=True, blank=True)




class Publish(models.Model):
    p_id = models.AutoField(verbose_name='ID', primary_key=True)  # 主键
    name = models.CharField(verbose_name='出版社名称', max_length=32)
    address = models.CharField(verbose_name='出版社地址', max_length=64)
    intro = models.CharField(verbose_name='出版社简介', null=True, blank=True, max_length=500)




class Book(models.Model):
    b_id = models.AutoField(verbose_name='ID', primary_key=True)
    name = models.CharField(verbose_name='书籍名称', max_length=50)
    isbn = models.CharField(verbose_name='ISBN', max_length=50)
    photo = models.ImageField(verbose_name='书籍封面', upload_to='imgs')
    price = models.DecimalField(verbose_name='价格', max_digits=5, decimal_places=2)
    publish = models.ForeignKey(to='Publish', to_field='p_id', on_delete=models.DO_NOTHING)
    author = models.ManyToManyField(to="Author", db_table='book_author')

           

使用SQLite数据库

SQLite是一款基于内存或者文件的、开源的、关系型的轻量级数据库。SQLite的移植性非常好,很容易使用,小巧、高效、可靠。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,甚至在iOS和Android的App中都可以集成。

SQLite数据库的目标就是尽量简单,抛弃了传统企业数据库的复杂特性,只实现了数据库的必备功能。虽然简单,但是功能和性能都非常出色。SQLite拥有完成的、自包含的数据库引擎。

SQLite数据库的一大特色就是在程序内部不需要网络配置和管理,没有管理员账户的概念,权限仅仅依赖于文件系统。

SQLite本身没有提供管理数据库的图形化界面,在不熟悉命令行的情况下,可以考虑通过一款图形化界面来完成管理工作,这里,推荐使用Navicat。

模型迁移

python manage.py makemigrations

python manage.py migrate

Django3+BootStrap开发图书管理系统,全网不可多得的学习资料
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

前端bootstrap框架介绍

Bootstrap

Bootstrap 是美国 Twitter 公司的设计师 Mark Otto 和 Jacob Thornton 合作基于 HTML、CSS、JavaScript 开发的简洁、直观、强悍的前端开发框架,使得 Web 开发更加快捷。Bootstrap 提供了优雅的 HTML 和 CSS 规范,它即是由动态 CSS 语言 Less 写成。(重点是响应式(随屏幕大小变化),能适应各种各种设备)

https://www.bootcss.com/

Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的。

AdminLTE

AdminLTE 是受欢迎的开源的管理仪表盘和控制面板的 WebApp 模板。它是基于 Bootstrap 的 CSS 框架,反应灵敏的 HTML 模板。利用所有 Bootstrap 的组件对大部分使用插件进行设计和调整风格,创建出可以用作后端应用程序的用户界面一致性设计。AdminLTE 是基于模块化设计,很容易在其之上定制和重制。

项目的页面是基于 AdminLTE 的模板来改造的,而 AdminLTE 又是基于 Bootstrap 框架,所以后续如果有新功能新样式要加,可以直接在 AdminLTE 官网找案例,或者 Bootstrap 官网找案例,都可以直接使用。

官网下载 : https://adminlte.io/

功能开发

出版社的列表

模板文件:

{% extends "base.html" %}
{% load static %}
{% block title %}
    <title>出版社列表</title>
{% endblock %}


{% block content %}
    <div class="content-wrapper">
        <div class="content-header">
            <div class="container-fluid">
                <div>
                    <div class="row">
                        <div class="col-sm-12">
                            <h1 class="m-0">
                                出版社模块
                                <small>列表</small>
                            </h1>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <!--内容开始-->
        <section class="content">
            <div class="container-fluid">
                <div class="row">
                    <div class="col-12 search-collapse">
                        <form id="search_form" method="post">
                            {% csrf_token %}
                            <div class="form-group row">
                                <label for="inputtext" class="col-form-label">出版社名称:</label>
                                <div class="col-md-4">
                                    <input type="text" id="search_name" name="name" class="form-control"/>
                                </div>
                                <div class="col-md-4">
                                    <button type="submit" class="btn btn-info"><i class="fa fa-plus"></i>查询</button>
                                    <a class="btn btn-primary single" href="{% url 'pub_add' %}">
                                        <i class="fa fa-plus"></i> 新增
                                    </a>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </section>


        <div class="col-sm-12 main">
            <br>
            <div class="panel panel-primary">
                <div class="panel-body">
                    <table class="table table-bordered table-condensed table-striped table-hover">
                        <thead>
                        <tr>
                            <th>序号</th>
                            <th>出版社名称</th>
                            <th>出版社地址</th>
                            <th>功能操作</th>
                        </tr>
                        </thead>
                        <tbody>
                        {% for per in pubs %}
                            <tr>
                                <td>{{ per.p_id }}</td>
                                <td>{{ per.name }}</td>
                                <td>{{ per.address }}</td>
                                <td width="20%">
                                    <a class="btn btn-primary single" href="{% url 'pub_edit' per.p_id %}">
                                        <i class="fa fa-edit"></i> 修改
                                    </a>
                                    <a class="btn btn-danger" href="javascript:void(0)" onclick="showDeleteModal(this)">删除</a>
                                    <input type="hidden" id="id_hidden" value={{ per.p_id }}>
                                </td>
                            </tr>
                        {% empty %}
                            <tr>
                                <td colspan="7">无相关记录!</td>
                            </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>


        <nav aria-label="Contacts Page Navigation">
            <ul class="pagination justify-content-center m-2">
                {% if pubs.has_previous %}
                    <li class="page-item">
                        <a class="page-link"
                           href="{% url 'pub_list' %}?page={{ pubs.previous_page_number }}&name={{ name }}">
                            <span aria-hidden="true">«</span>
                        </a>
                    </li>
                {% endif %}


                {% for pg in pubs.paginator.page_range %}
                    {% if pubs.number == pg %}
                        <li class="page-item active">
                            <a class="page-link" href="">{{ pg }}</a>
                        </li>
                    {% else %}
                        <li class="page-item">
                            <a class="page-link"
                               href="{% url 'pub_list' %}?page={{ pg }}&name={{ name }}</a>
                        </li>
                    {% endif %}
                {% endfor %}




                {% if pubs.has_next %}
                    <li class="page-item">
                        <a class="page-link"
                           href="{% url 'pub_list' %}?page={{ pubs.next_page_number }}&name={{ name }}">
                            <span aria-hidden="true">»</span>
                        </a>
                    </li>
                {% endif %}
            </ul>
        </nav>
    </div>


    <!-- 信息删除确认 -->
    <div class="modal fade" id="delModal" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title" style="float:left">提示信息</h4>
                    <button type="button" class="close" data-dismiss="modal"
                            aria-label="Close">
                        <span aria-hidden="true">×</span>
                    </button>


                </div>
                <div class="modal-body">
                    <p id="info">您确认要删除当前数据吗?</p>
                    <input type="hidden" id="del_id">
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                    <a id="delButton" class="btn btn-success" data-dismiss="modal">确定</a>
                </div>
            </div>
        </div>
    </div>
    <script>
        // 打开模态框并设置需要删除的ID
        function showDeleteModal(obj) {
            var $tds = $(obj).parent().children();// 获取到删除元素的所在列
            var delete_id = $($tds[2]).val();// 获取隐藏控件的ID
            console.log(delete_id)
            $("#del_id").val(delete_id);// 给模态框中需要删除的ID赋值
            $("#delModal").modal({
                backdrop: 'static',
                keyboard: false
            });
        };


        $(function () {
            // 模态框的确定按钮的点击事件
            $("#delButton").click(function () {
                var id = $("#del_id").val();
                console.log("del" + id)
                // ajax异步删除
                $.ajax({
                    url: "/users/del/" + id + "/",
                    type: "GET",
                    success: function (result) {
                        if (result.code == "200") {
                            $("#delModal").modal("hide");
                            //window.location.href = "/users/index/";
                        }
                    }
                })
            });
        });
</script>
{% endblock %}           

视图函数:

@permission_required("publish_view")
@login_required
def publish_list(request):
    if request.method == "GET":
        pubs = Publish.objects.all()
        return render(request, "publish/index.html", {'pubs': pubs})
    if request.method == "POST":
        name = request.POST.get("name")
        if name:
            pubs = Publish.objects.filter(name__contains=name)
        else:
            pubs = Publish.objects.all()
        return render(request, "publish/index.html", {'pubs': pubs})           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

出版社的新增

模板页面:

{% extends "base.html" %}
{% load static %}
{% block ext_title %}
    <title>出版社信息新增</title>
{% endblock %}
{% block content %}
    <div class="content-wrapper">
        <section class="content-header">
            <div class="container-fluid">
                <div class="row mb-2">
                    <div class="col-sm-12">
                        <ol class="breadcrumb float-sm-left">
                            <li class="breadcrumb-item"><a href="#">出版社管理</a></li>
                            <li class="breadcrumb-item active">出版社增加</li>
                        </ol>
                    </div>
                </div>
            </div>
        </section>
        <section class="content">
            <div class="container-fluid">
                <div class="row">
                    <!-- left column -->
                    <div class="col-md-12">
                        <!-- Horizontal Form -->
                        <div class="card card-info">
                            <div class="card-header">
                                <h3 class="card-title">出版社信息增加</h3>
                            </div>
                            <!-- /.card-header -->
                            <!-- form start -->
                            <form class="form-horizontal" method="post" novalidate>
                                {% csrf_token %}
                                <div class="card-body">
                                    <div class="form-group row">
                                        <!--<label for="inputtext class="col-sm-2 col-form-label">出版社名称</label>-->
                                        <label for="{{ form.name.id_for_label }}"
                                               class="col-sm-2 col-form-label">{{ form.name.label }}</label>
                                        <div class="col-sm-10">
                                            <!--<input type="text" class="form-control" id="name" name="name" placeholder="出版社名称">-->
                                            {{ form.name }}
                                            <span style="color:red">{{ errors.name.0 }}</span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="inputtext" class="col-sm-2 col-form-label">出版社地址</label>
                                        <div class="col-sm-10">
                                            <!--<input type="text" class="form-control" id="address" name="address" placeholder="出版社地址">-->
                                            {{ form.address }}
                                            <span style="color:red">{{ errors.address.0 }}</span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="inputtext" class="col-sm-2 col-form-label">出版社简介</label>
                                        <div class="col-sm-10">
                                            {{ form.intro }}
                                            {#                      <textarea class="form-control" rows="3" id="intro" name="intro" placeholder="出版社简介"></textarea>#}
                                        </div>
                                    </div>
                                </div>
                                <!-- /.card-body -->
                                <div class="card-footer">
                                    <button type="submit" class="btn btn-info">保存</button>
                                    <button type="button" class="btn btn-default"
                                            onclick="javascript:window.location='{% url "pub_list" %}'">返回
                                    </button>
                                    <span style="color:red">{{ info }}</span>
                                </div>
                                <!-- /.card-footer -->
                            </form>
                        </div>
                        <!-- /.card -->
                    </div>


                    <!--/.col (right) -->
                </div>
                <!-- /.row -->
            </div><!-- /.container-fluid -->
        </section>
    </div>
{% endblock %}           

视图函数:

@login_required
def publish_add(request):
    if request.method == "GET":
        f = PublishForm()
        return render(request, "publish/add.html", {"form": f})
    elif request.method == "POST":
        f = PublishForm(request.POST)
        if f.is_valid():
            name = f.cleaned_data.get("name")
            vname = Publish.objects.filter(name=name)
            if vname:
                info = "出版社名称已经存在,请查询"
                return render(request, "publish/add.html", {'form': f, 'info': info})
            else:
                Publish.objects.create(**f.cleaned_data)
                return redirect(reverse("pub_list"))
        else:
            errors = f.errors
            return render(request, "publish/add.html", {'form': f, 'errors': errors})           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

出版社的修改

视图函数

@login_required
def publish_edit(request, pid):
    if request.method == "GET":
        pub_obj = Publish.objects.filter(p_id=pid).first()
        f = PublishForm({
            "name": pub_obj.name,
            "address": pub_obj.address,
            "intro": pub_obj.intro,
        })
        return render(request, "publish/edit.html", {'form': f})
    elif request.method == "POST":
        f = PublishForm(request.POST)
        pub_item = Publish.objects.filter(p_id=pid).first()
        if f.is_valid():
            pub = Publish.objects.get(p_id=pid)
            pub.name = f.cleaned_data.get("name")
            pub.address = f.cleaned_data.get("address")
            pub.intro = f.cleaned_data.get("intro")
            pub.save()
            return redirect(reverse("pub_list"))
        else:
            errors = f.errors
            return render(request, "publish/edit.html", {'form': f, 'errors': errors})           

出版社的删除

Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

作者的列表

视图函数:

@login_required
def author_list(request):
    if request.method == "GET":
        datas = Author.objects.all().order_by("-a_id")
        page_size = 5
        page = request.GET.get("page", 1)
        pages = Paginator(datas, page_size)
        authors = pages.page(page)
        return render(request, "author/index.html", {'authors': authors})
    if request.method == "POST":
        name = request.POST.get("name")
        mobile = request.POST.get("mobile")
        search = dict()
        if name:
            search["name__contains"] = name
        if mobile:
            search["mobile"] = mobile
        datas = Author.objects.filter(**search).order_by("-a_id")

        page_size = 5
        page = request.POST.get("page", 1)
        pages = Paginator(datas, page_size)
        authors = pages.page(page)
        print(authors)
        return render(request, "author/index.html", {'authors': authors})           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

图书的列表

视图函数:

@login_required
def book_list(request):
    if request.method == "GET":
        f = BookForm()
        datas = Book.objects.all().order_by("-b_id")
        page_size = 5
        page = request.GET.get("page", 1)
        pages = Paginator(datas, page_size)
        books = pages.page(page)
        return render(request, "book/index.html", {'form': f, 'books': books})
    if request.method == "POST":
        p_id = request.POST.get("publish", '0')
        name = request.POST.get("name")
        search = dict()
        if name:
            search["name__contains"] = name
        if p_id:
            search["publish_id"] = p_id
        datas = Book.objects.filter(**search).order_by("-b_id")
        f = BookForm({
            "name": name,
            "publish": p_id,
        })
        page_size = 5
        page = request.POST.get("page", 1)
        pages = Paginator(datas, page_size)
        books = pages.page(page)
        context = {
            "name": name,
            "publish": p_id,
            "books": books,
            "form": f,
        }
        print(context)
        return render(request, "book/index.html", context=context)           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

图书和作者的多对多,出版社和图书的一对多

图书的新增

视图函数:

@login_required
def book_add(request):
    if request.method == "GET":
        f = BookForm()
        return render(request, "book/add.html", {'form': f})
    elif request.method == "POST":
        f = BookForm(request.POST)
        if f.is_valid():
            book = Book()
            book.name = f.cleaned_data.get("name")
            book.isbn = f.cleaned_data.get("isbn")
            book.photo = f.cleaned_data.get("photo")
            book.price = f.cleaned_data.get("price")
            book.publish_id = f.cleaned_data.get("publish")
            # 或者使用publish实例
            # publish_id=f.cleaned_data.get("publish")
            # pub_obj=Publish.objects.filter(p_id=publish_id).first()
            # book.publish=pub_obj
            book.save()
            #返回自增id
            b_id=book.b_id
            book_obj=Book.objects.filter(b_id=b_id).first()
            #获取前台多选框内的作者信息
            select_authors=request.POST.getlist("author")
            alist = [i for i in select_authors]
            #调用set指令,实际上是先删后插
            book_obj.author.set(alist)
            return redirect(reverse("book_list"))
        else:
            errors = f.errors
            return render(request, "book/add.html", {'form': f, 'errors': errors})           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

图书的修改

模板文件:

{% extends "base.html" %}
{% load static %}
{% block ext_title %}
    <title>图书信息修改</title>
{% endblock %}
{% block content %}
    <div class="content-wrapper">
        <section class="content-header">
            <div class="container-fluid">
                <div class="row mb-2">
                    <div class="col-sm-12">
                        <ol class="breadcrumb float-sm-left">
                            <li class="breadcrumb-item"><a href="#">图书管理</a></li>
                            <li class="breadcrumb-item active">图书修改</li>
                        </ol>
                    </div>
                </div>
            </div>
        </section>
        <section class="content">
            <div class="container-fluid">
                <div class="row">
                    <!-- left column -->
                    <div class="col-md-12">
                        <!-- Horizontal Form -->
                        <div class="card card-info">
                            <div class="card-header">
                                <h3 class="card-title">图书信息修改</h3>
                            </div>
                            <!-- /.card-header -->
                            <!-- form start -->
                            <form class="form-horizontal" method="post" enctype="multipart/form-data" novalidate>
                                {% csrf_token %}
                                <div class="card-body">
                                    <div class="form-group row">
                                        <label for="inputtext" class="col-sm-2 col-form-label">图书名称</label>


                                        <div class="col-sm-10">
                                            <input type="text" class="form-control" id="name" name="name"
                                                   value="{{ book.name }}" placeholder="图书名称">
                                            <span style="color:red">{{ errors.name.0 }}</span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="inputtext" class="col-sm-2 col-form-label">ISBN</label>
                                        <div class="col-sm-10">
                                            <input type="text" class="form-control" id="isbn" name="isbn"
                                                   value="{{ book.isbn }}" placeholder="请输入ISBN">
                                            <span style="color:red">{{ errors.isbn.0 }}</span>
                                        </div>
                                    </div>


                                    <div class="form-group row">
                                        <label for="inputtext" class="col-sm-2 col-form-label">图书封面</label>
                                        <div class="col-sm-8">
                                            <div class="input-group">
                                                <div class="custom-file">
                                                    {{ form.photo }}
                                                    <label class="custom-file-label">选择图书封面</label>
                                                </div>
                                            </div>
                                            <!--<input type="file" name="photo"  value="{{ book.photo }}"  id="photo">-->
                                            {% if book.photo %}
                                                <img id="preview-image" src="media/{{ book.photo }}"
                                                     style="width: 150px; height: 150px;"/>
                                            {% else %}
                                                <img id="preview-image" src="{% static 'img/default-150x150.png' %}"
                                                     style="width: 150px; height: 150px;"/>
                                            {% endif %}
                                            <span style="color:red">{{ errors.photo.0 }}</span>
                                        </div>
                                    </div>


                                    <div class="form-group row">
                                        <label for="inputtext" class="col-sm-2 col-form-label">价格</label>
                                        <div class="col-sm-10">
                                            <input type="text" class="form-control" id="price" name="price"
                                                   value="{{ book.price }}" placeholder="请输入价格">
                                            <span style="color:red">{{ errors.price.0 }}</span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="inputtext" class="col-sm-2 col-form-label">出版社</label>
                                        <div class="col-sm-10">
                                            {{ form.publish }}
                                            <span style="color:red">{{ errors.publish_id.0 }}</span>
                                        </div>
                                    </div>


                                    <div class="form-group row">
                                        <label for="inputtext" class="col-sm-2 col-form-label">作者</label>
                                        <div class="col-sm-10">
                                            {{ form.author }}
                                            <span style="color:red">{{ errors.author_id.0 }}</span>
                                        </div>
                                    </div>
                                </div>
                                <!-- /.card-body -->
                                <div class="card-footer">
                                    <button type="submit" class="btn btn-info">保存</button>
                                    <button type="button" class="btn btn-default"
                                            onclick="javascript:window.location='{% url "book_list" %}'">返回
                                    </button>
                                    <span style="color:red">{{ errors }}</span>
                                </div>
                                <!-- /.card-footer -->
                            </form>
                        </div>
                        <!-- /.card -->
                    </div>


                    <!--/.col (right) -->
                </div>
                <!-- /.row -->
            </div><!-- /.container-fluid -->
        </section>
    </div>
    <script language="JavaScript">
        $('[name="photo"]').bind('change', function () {
            var file = this.files[0];
            var rdr = new FileReader();
            rdr.onload = function () {
                $('#preview-image').attr('src', this.result);
            };
            rdr.readAsDataURL(file);
        });
</script>
{% endblock %}           

视图函数:

@login_required
def book_edit(request, bid):
    if request.method == "GET":
        # 根据bid找到具体的图书
        book_obj = Book.objects.filter(b_id=bid).first()
        # 找到出版社
        publish_obj = book_obj.publish
        author_ids = (book_obj.author.values_list('a_id','name'))
        #zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
        #*author_ids相当于zip反向操作
        author_ids = list(zip(*author_ids))[0] if list(zip(*author_ids)) else []
        print(author_ids)
        f = BookForm(initial={
            "name": book_obj.name,
            "isbn": book_obj.isbn,
            "photo": book_obj.photo,
            #将p_id赋值给publish
            "publish": publish_obj.p_id,
            #将(1,2,3)元组赋值给多对多author
            "author":author_ids,
        })
        return render(request, "book/edit.html", {'form': f, 'book': book_obj})
    elif request.method == "POST":
        f = BookForm(request.POST, request.FILES)
        book_item = Book.objects.filter(b_id=bid).first()
        if f.is_valid():
            book = Book.objects.get(b_id=bid)
            book.name = f.cleaned_data.get("name")
            book.isbn = f.cleaned_data.get("isbn")
            book.photo = f.cleaned_data.get("photo")
            book.price = f.cleaned_data.get("price")
            book.publish_id = f.cleaned_data.get("publish")
            book.save()
            # 获取前台多选框内的作者信息
            select_authors = request.POST.getlist("author")
            alist = [i for i in select_authors]
            # 调用set指令,实际上是先删后插
            book.author.set(alist)
            return redirect(reverse("book_list"))
        else:
            errors = f.errors
            print(errors)
            return render(request, "book/edit.html", {'form': f, 'book': book_item, 'errors': erro           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

用户管理

视图函数:

@login_required
def user_list(request):
    users = User.objects.all()
    return render(request, "users/index.html", {'users': users})           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

组管理

视图函数:

@login_required
def group_list(request):
    groups = Group.objects.all()
    return render(request, "group/index.html", {'groups': groups})           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

首页的展示

视图函数:

@login_required
def index(request):
    # 获取统计信息
    pub_count = Publish.objects.all().count()
    author_count = Author.objects.all().count()
    book_count = Book.objects.all().count()

    # 图表的label和data组装
    infos = Book.objects.values('publish__name').annotate(Count('name'))
    for info in infos:
        print(info["publish__name"])
    labels = [info["publish__name"] for info in infos]
    print(labels)
    datas = [info["name__count"] for info in infos]
    print(datas)
    context = {
        "pub_count": pub_count,
        "author_count": author_count,
        "book_count": book_count,
        "labels": labels,
        "datas": datas,
    }
    return render(request, 'index.html', context=context)           
Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

Admin后台管理

admin.py文件

from django.contrib import admin
from django.utils.safestring import mark_safe
from django.utils.html import format_html
from .models import *

# Register your models here.
admin.site.site_title = "Django开发的图书管理系统"
admin.site.site_header = "欢迎来到我的图书管理系统"
admin.site.index_title = "图书管理系统后台管理"


@admin.register(Publish)
class Publish(admin.ModelAdmin):
    pass


@admin.register(Author)
class Author(admin.ModelAdmin):
    pass


@admin.register(Book)
class Book(admin.ModelAdmin):
pass
           

需要代码,请站内私信我。

更多Django内容,请关注 Django + Vue.js实战派――Python Web开发与运维

Django3+BootStrap开发图书管理系统,全网不可多得的学习资料

需要代码,请站内私信我。