Django项目实战(二):图书管理系统---多表操作版

一、效果展示

1、图书展示界面

在这里插入图片描述

2、图书删除功能

在这里插入图片描述

3、图书添加功能

在这里插入图片描述

4、图书编辑功能

在这里插入图片描述

解决了上次图书管理系统的删除序号重排问题,也全部采用了系统自建主键!优化了界面

项目不足之处:
由于多表操作,因此作者和出版社只能在那几个当中选择,都是限制死了的,没有写出添加出版社和作者的web接口!

二、项目目录展示

在这里插入图片描述
大致流程:
1、先把项目所用数据库准备好,改settings、\_\_init__文件把数据库连接好
2、然后设置url和视图函数映射关系,视图函数通过操作数据库,返回模板语法渲染好的页面,或者临时重定向到其他url对应的视图函数(我这里临时重定向的全是主页,因为数据修改完,就跳转到主页展示修改后的效果嘛)!
3、无论是模板中的html,还是视图函数都不要采用硬编码url,都应该使用name反向解析!

三、项目源码

1、models.py

from django.db import models


# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=30)
    price = models.IntegerField()
    pub_date = models.DateField()
    authors = models.ManyToManyField(to="Authors")  # 多对多
    publish = models.ForeignKey(to="Publisher", on_delete=models.CASCADE)  # 一对多,只有外键才有级联删除这一说。多对多是另外开一张表,不存在

    def __str__(self):
        return self.name


class Authors(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
    ad = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE)

    def __str__(self):
        return self.name


class AuthorDetail(models.Model):
    email = models.EmailField()
    tel_phone = models.IntegerField()


class Publisher(models.Model):
    name = models.CharField(max_length=30)
    email = models.EmailField()

    def __str__(self):
        return self.name

这里面的AuthorDetail表,只是为了练习作者与作者详细之间的OneToOneField关系!对图书管理系统并没有实际意义!

2、urls.py

from django.contrib import admin
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.book_view, name='book_view'),
    path('books/add', views.book_add, name='book_add'),
    re_path('books/del/(?P<del_book_id>[0-9]+)/', views.book_del, name='book_del'),
    re_path('books/edit/(?P<edit_book_id>[0-9]+)/', views.book_edit, name='book_edit')
]

3、views.py

from django.shortcuts import render
from app01.models import Book, Publisher, Authors
from django.shortcuts import redirect, reverse


# Create your views here.
def book_view(request):
    book_list = Book.objects.all()
    return render(request, "index.html", {'book_list': book_list})


def book_add(request):
    if request.method == 'GET':
        publisher_list = Publisher.objects.all()
        author_list = Authors.objects.all()
        return render(request, 'add.html', {'publisher_list': publisher_list, 'author_list': author_list})
    else:
        name = request.POST.get('name')
        price = request.POST.get('price')
        pub_date = request.POST.get('pub_date')
        publisher_id = request.POST.get('publisher_id')
        authors_id = request.POST.getlist('authors_id[]')  # 这里得到的是一个author列表
        book = Book.objects.create(name=name, price=price, pub_date=pub_date, publish_id=publisher_id)
        book.authors.add(*authors_id)  # *号:列表打散
        return redirect(reverse('book_view'))


def book_del(request, del_book_id):
    Book.objects.filter(pk=del_book_id).delete()
    return redirect(reverse('book_view'))


def book_edit(request, edit_book_id):
    book_obj = Book.objects.filter(pk=edit_book_id).first()
    if request.method == 'GET':
        publisher_list = Publisher.objects.all()
        author_list = Authors.objects.all()
        return render(request, 'edit.html', {'book_obj': book_obj, 'publisher_list': publisher_list, 'author_list': author_list})
    else:
        name = request.POST.get('name')
        price = request.POST.get('price')
        pub_date = request.POST.get('pub_date')
        publisher_id = request.POST.get('publisher_id')
        authors_id = request.POST.getlist('authors_id[]')
        Book.objects.update(name=name, price=price, pub_date=pub_date, publish_id=publisher_id)
        book_obj.authors.set(*authors_id)
        return redirect(reverse('book_view'))

4、模板

(1)index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>图书管理系统</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .table_area {
            width: 800px;
            position: absolute;
            top: 150px;
            left: 250px;
        }
        .add_btn {
            font-size: 18px;
            font-family: "Kaiti SC";
            font-weight: bolder;
        }
    </style>
</head>
<body>
<div class="table_area">
    <table class="table table-hover">
        <thead>
        <tr>
            <th>书籍编号</th>
            <th>书名</th>
            <th>价格</th>
            <th>出版时间</th>
            <th>出版社</th>
            <th>作者</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        {% for book_obj in book_list %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ book_obj.name }}</td>
                <td>{{ book_obj.price }}</td>
                <td>{{ book_obj.pub_date|date:'Y-m-d' }}</td>
                <td>{{ book_obj.publish.name }}</td>
                <td>
                    {% for author_obj in book_obj.authors.all %} <!--book_obj.authors.all得到的是一个作者对象的queryset-->
                        {% if forloop.last %}
                            <!--
                                有人会问这里不是对象吗?为什么打印对象?不应该是author_obj.name吗?
                                我在model中写了双下方法str的
                            -->
                            {{ author_obj }}
                        {% else %}
                            {{ author_obj }},
                        {% endif %}

                    {% endfor %}
                </td>
                <td>
                    <a href="{% url 'book_edit' book_obj.pk %}" class="btn btn-warning btn-xs">编辑</a>
                    <a href="{% url 'book_del' book_obj.pk %}" class="btn btn-danger btn-xs">删除</a>
                </td>
            </tr>
            {% if forloop.last and forloop.counter > 0 %}
                <tr>
                    <td colspan="7">
                        <a href="{% url 'book_add' %}" class="btn btn-info btn-xs form-control add_btn">添加书籍</a>
                    </td>
                </tr>
            {% endif %}
        {% empty %}
            <tr align="center">
                <td colspan="7">
                    暂未上架任何书籍... <br>
                    <span>请点击:<a href="{% url 'book_add' %}" class="btn btn-info btn-xs">添加书籍</a></span>
                </td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
</html>
(2)add.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>图书管理系统</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .form-area {
            width: 600px;
            position: absolute;
            top: 130px;
            left: 300px;
        }

        h3 {
            position: relative;
            left: 270px;
            margin-bottom: 20px;
            font-family: "Kaiti SC";
            font-weight: bold;
        }

        .center-block {
            position: relative;
            left: 50px;
        }

        .author_add {
            position: relative;
            top: 20px;
        }

        #inputauthor {
            height: 75px;
        }
    </style>
</head>
<body>
<div class="form-area">
    {% block form_title %}
        <h3>书籍添加信息表</h3>
    {% endblock form_title %}
    {% block form_head %}
        <form class="form-horizontal" action="{% url 'book_add' %}" method="post">
    {% endblock form_head %}
    {% csrf_token %}
    <div class="form-group">
        <label for="inputname" class="col-sm-2 control-label">书名</label>
        <div class="col-sm-10">
            {% block inputname %}
                <input type="text" class="form-control" id="inputname" placeholder="请输入书籍名称" name="name">
            {% endblock inputname %}
        </div>
    </div>
    <div class="form-group">
        <label for="inputprice" class="col-sm-2 control-label">价格</label>
        <div class="col-sm-10">
            {% block inputprice %}
                <input type="text" class="form-control" id="inputprice" placeholder="请输入价格" name="price">
            {% endblock inputprice %}
        </div>
    </div>
    <div class="form-group">
        <label for="input_pub_date" class="col-sm-2 control-label">出版时间</label>
        <div class="col-sm-10">
            {% block input_pub_date %}
                <input type="date" class="form-control" id="input_pub_date" name="pub_date">
            {% endblock input_pub_date %}
        </div>
    </div>
    <div class="form-group">
        <label for="inputpublisher" class="col-sm-2 control-label">出版社</label>
        <div class="col-sm-10">
            {% block inputpublisher %}
                <select name="publisher_id" id="inputpublisher" class="form-control">
                    {% for publish_obj in publisher_list %}
                        <option value="{{ publish_obj.pk }}">{{ publish_obj }}</option>
                    {% endfor %}
                </select>
            {% endblock inputpublisher %}
        </div>
    </div>
    <div class="form-group">
        <label for="inputauthor" class="col-sm-2 control-label author_add">作者</label>
        <div class="col-sm-10">
            {% block inputauthor %}
                <select name="authors_id[]" id="inputauthor" class="form-control" multiple>
                    {% for author_obj in author_list %}
                        <option value="{{ author_obj.pk }}">{{ author_obj }}</option>
                    {% endfor %}
                </select>
            {% endblock inputauthor %}
        </div>
    </div>
    {% block submit %}
        <input type="submit" class="btn btn-success center-block" value="提交">
    {% endblock submit %}
    {% block form-tail %}
        </form>
    {% endblock form-tail %}
</div>
</body>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在bootstrap前边) -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
</html>
(3)edit.html

由于本页面和add.html及其相似,因此这里采用了模板继承

{% extends 'add.html' %}
{% block form_title %}
    <h3>书籍信息编辑表</h3>
{% endblock form_title %}

{% block form_head %}
    <form class="form-horizontal" action="{% url 'book_edit' book_obj.pk %}" method="post">
{% endblock form_head %}

{% block inputname %}
    <input type="text" class="form-control" id="inputname" name="name" value="{{ book_obj.name }}">
{% endblock inputname %}

{% block inputprice %}
    <input type="text" class="form-control" id="inputprice" name="price" value="{{ book_obj.price }}">
{% endblock inputprice %}

{% block input_pub_date %}
    <input type="date" class="form-control" id="input_pub_date" name="pub_date" value="{{ book_obj.pub_date|date:'Y-m-d' }}">
{% endblock input_pub_date %}

{% block inputpublisher %}
    <select name="publisher_id" id="inputpublisher" class="form-control">
        {% for publish_obj in publisher_list %}
            {% if book_obj.publish == publish_obj %}
                <option value="{{ publish_obj.pk }}" selected>{{ publish_obj }}</option>
            {% else %}
                <option value="{{ publish_obj.pk }}">{{ publish_obj }}</option>
            {% endif %}
        {% endfor %}
    </select>
{% endblock inputpublisher %}

{% block inputauthor %}
    <select name="authors_id[]" id="inputauthor" multiple class="form-control">
        {% for author_obj in author_list %}
            {% if author_obj in book_obj.authors.all %}
                <option value="{{ author_obj.pk }}" selected>{{ author_obj }}</option>
            {% else %}
                <option value="{{ author_obj.pk }}">{{ author_obj }}</option>
            {% endif %}
        {% endfor %}
    </select>
{% endblock inputauthor %}

{% block submit %}
    <input type="submit" class="btn btn-success center-block" value="提交修改">
{% endblock submit %}

{% block form-tail %}
    </form>>
{% endblock form-tail %}

四、项目心得总结

1、注意事项

注意publish和publish_id的区别,authors并不是一个字段,而是用来供我们操纵关系表的一个接口!

2、select多选框的实现方法

在这里插入图片描述
name后一定要加[],不然接受到的就是一个值,而不是一个多选的列表!
在这里插入图片描述
不能再用get了,需要用getlist!获得的列表就可以直接*号打散传值!

猜你喜欢

转载自blog.csdn.net/weixin_44571270/article/details/107598330
今日推荐