天天看點

Django3+BootStrap開發圖書管理系統,全網不可多得的學習資料

作者:Python有溫度

本案例主要示範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開發圖書管理系統,全網不可多得的學習資料

需要代碼,請站内私信我。