开发一个简易的图书增删改查页面

摘要:
需求"""1.实现用户登录、注册2.列出图书列表、出版社列表、作者列表3.点击作者,会在新的页面列出该作者出版的图书列表4.点击出版社,会列出该出版社旗下图书列表5.可以创建、修改、删除图书、作者、出版社A.点击修改书籍按钮,弹出模态框,模态框中展示该书的信息且信息可以修改,B.书名不可重复,不可修改C.修改图书信息时,使用ajax请求发送信息"""页面展示项目目录结构(前端用到了jQuery/b

需求

"""1. 实现用户登录、注册
2. 列出图书列表、出版社列表、作者列表
3. 点击作者,会在新的页面列出该作者出版的图书列表
4. 点击出版社,会列出该出版社旗下图书列表
5. 可以创建、修改、删除  图书、作者、出版社

A. 点击修改书籍按钮,弹出模态框,模态框中展示该书的信息且信息可以修改,
B. 书名不可重复,不可修改
C. 修改图书信息时,使用ajax请求发送信息
"""

页面展示

开发一个简易的图书增删改查页面第1张开发一个简易的图书增删改查页面第2张

开发一个简易的图书增删改查页面第3张

开发一个简易的图书增删改查页面第4张开发一个简易的图书增删改查页面第5张开发一个简易的图书增删改查页面第6张

开发一个简易的图书增删改查页面第7张开发一个简易的图书增删改查页面第8张开发一个简易的图书增删改查页面第9张

项目目录结构(前端用到了jQuery/bootstrap/sweetalert)

开发一个简易的图书增删改查页面第10张

app01文件夹

models.py

from django.db importmodels

#Create your models here.


"""Book              与Publish多对一;与Author多对多
Author
Publish
Book2Author
"""


classPublish(models.Model):
    """出版社名称和出版社邮箱两个字段是联合索引"""pid =models.AutoField(
        primary_key=True,
        verbose_name="主键",
    )
    pub_name =models.CharField(
        max_length=32,
        verbose_name="出版社名称",
    )
    pub_addr =models.CharField(
        max_length=64,
        verbose_name="出版社地址",
    )
    pub_email =models.EmailField(
        verbose_name="出版社邮箱",
    )

    classMeda:
        unique_together = (("pub_name", "pub_email"),)
        ordering = ['-id']


classAuthor(models.Model):
    """作者名字字段是唯一索引"""aid =models.AutoField(
        primary_key=True,
        verbose_name="主键",
    )
    author_name =models.CharField(
        max_length=32,
        unique=True,
        verbose_name="作者名字",
    )
    author_gender_choices =(
        (1, ""),
        (2, ""),
        (3, "其他"),
    )
    author_gender =models.IntegerField(
        choices=author_gender_choices,
        default=1,
        verbose_name="作者性别",
    )


classBook(models.Model):
    """书籍名称这个字段是唯一索引"""bid =models.AutoField(
        primary_key=True,
        verbose_name="主键",
    )
    book_name =models.CharField(
        max_length=32,
        verbose_name="书籍名称",
        unique=True,
    )
    book_price =models.DecimalField(
        max_digits=8,
        decimal_places=2,
        verbose_name="书籍价格",
    )
    book_date =models.DateField(
        verbose_name="书籍出版日期",
    )
    publish = models.ForeignKey(to="Publish", on_delete=models.CASCADE)
    authors = models.ManyToManyField(to="Author")

myforms.py

from django importforms
from app01.models import *


classMylogin(forms.Form):
    """登录校验"""username =forms.CharField(
        label="账号",
        min_length=3,
        max_length=9,
        error_messages={
            "required": "账号不能为空",
            "min_length": "账号不能小于3位",
            "max_length": "账号不能大于9位",
        },
        widget=forms.widgets.TextInput(attrs={"class": "form-control"}),
    )
    password =forms.CharField(
        label="密码",
        min_length=3,
        max_length=9,
        error_messages={
            "required": "密码不能为空",
            "min_length": "密码不能小于3位",
            "max_length": "密码不能大于9位",
        },
        widget=forms.widgets.PasswordInput(attrs={"class": "form-control"}),
    )


classMyreg(forms.Form):
    """注册校验"""username =forms.CharField(
        label="账号",
        min_length=3,
        max_length=9,
        error_messages={
            "required": "账号不能为空",
            "min_length": "账号不能小于3位",
            "max_length": "账号不能大于9位",
        },
        widget=forms.widgets.TextInput(attrs={"class": "form-control"}),
    )
    password =forms.CharField(
        label="密码",
        min_length=3,
        max_length=9,
        error_messages={
            "required": "密码不能为空",
            "min_length": "密码不能小于3位",
            "max_length": "密码不能大于9位",
        },
        widget=forms.widgets.PasswordInput(attrs={"class": "form-control"}),
    )
    confirm_password =forms.CharField(
        label="确认密码",
        min_length=3,
        max_length=9,
        error_messages={
            "required": "确认密码不能为空",
            "min_length": "密码不能小于3位",
            "max_length": "密码不能大于9位",
        },
        widget=forms.widgets.PasswordInput(attrs={"class": "form-control"}),
    )
    user_email =forms.EmailField(
        label="邮箱",
        error_messages={
            "invalid": "邮箱格式不正确",
            "required": "邮箱不能为空",
        },
        widget=forms.widgets.EmailInput(attrs={"class": "form-control"}),
    )

    defclean_user(self):
        """校验用户名是否包含特定字符"""username = self.cleaned_data.get("username")
        if "666" inusername:
            self.add_error("username", "要自己666才行呀!!!")
        returnusername

    defclean(self):
        """校验密码和确认密码是否一致"""password = self.cleaned_data.get("password")
        confirm_password = self.cleaned_data.get("confirm_password")
        if not password ==confirm_password:
            self.add_error("confirm_password", "两次密码不一致!!!")
        returnself.cleaned_data


classAddBook(forms.Form):
    """添加书籍校验"""book_name =forms.CharField(
        max_length=16,
        error_messages={
            "required": "书名不能为空",
            "max_length": "书名不能大于16位",
        },
    )
    book_price =forms.FloatField(
        min_value=0.01,
        max_value=999999.99,
        error_messages={
            "min_value": "最小价格不能小于0.01",
            "max_value": "最大价格不能大于999999.99",
            "required": "价格不能为空",
        },
    )

    defclean_book_name(self):
        """校验书名是否重复"""book_name = self.cleaned_data.get("book_name")
        book_obj =Book.objects.filter(
            book_name=book_name
        ).first()
        ifbook_obj:
            self.add_error("book_name", "书籍已存在,请重新输入...")
        returnbook_name


classSetPassword(forms.Form):
    old_password =forms.CharField(
        label="原密码",
        min_length=3,
        max_length=9,
        error_messages={
            "required": "原密码不能为空",
            "min_length": "密码不能小于3位",
            "max_length": "密码不能大于9位",
        },
        widget=forms.widgets.PasswordInput(attrs={"class": "form-control"}),
    )
    new_password =forms.CharField(
        label="新密码",
        min_length=3,
        max_length=9,
        error_messages={
            "required": "新密码不能为空",
            "min_length": "新密码不能小于3位",
            "max_length": "新密码不能大于9位",
        },
        widget=forms.widgets.PasswordInput(attrs={"class": "form-control"}),
    )
    confirm_password =forms.CharField(
        label="确认密码",
        min_length=3,
        max_length=9,
        error_messages={
            "required": "确认密码不能为空",
            "min_length": "确认密码不能小于3位",
            "max_length": "确认密码不能大于9位",
        },
        widget=forms.widgets.PasswordInput(attrs={"class": "form-control"}),
    )

    defclean(self):
        new_password = self.cleaned_data.get("new_password")
        confirm_password = self.cleaned_data.get("confirm_password")
        if not new_password ==confirm_password:
            self.add_error("confirm_password", "两次密码不一致,请重新输入...")
        return self.cleaned_data

test.py

from django.test importTestCase

#Create your tests here.

importos

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "six_module_one_work.settings")
    importdjango
    django.setup()
    from app01.models import *
    #创建初始系统账户admin
    #from django.contrib.auth.models import User
    #user = User.objects.create_superuser(username='admin', password='asd123123', email='123@qq.com')

    #创建初始作者表
    #author_list = []
    #for i in range(1, 6):
    #author_obj = Author(
    #author_name='jack%s' % i,
    #author_gender=1,
    #)
    #author_list.append(author_obj)
    #Author.objects.bulk_create(author_list)

    #创建初始出版社表
    #publish_list = []
    #for i in range(1, 6):
    #publish_obj = Publish(
    #pub_name="北京出版社%s" % i,
    #pub_addr="北京市%s街道%s巷" % (i, i),
    #pub_email="%s%s%s@163.com" % (i, i, i),
    #)
    #publish_list.append(publish_obj)
    #Publish.objects.bulk_create(publish_list)

    #创建初始书籍表
    #book_list = []
    #for i in range(1, 251):
    #book_obj = Book(
    #book_name="python%s" % i,
    #book_price=i,
    #book_date="2021-02-02",
    #publish_id=1,
    #)
    #book_list.append(book_obj)
    #Book.objects.bulk_create(book_list)

    #创建作者书籍关系表
    #for i in range(1, 126):
    #book_obj = Book.objects.filter(bid=i).first()
    #book_obj.authors.add(1, 3, 5)
    #for i in range(126, 251):
    #book_obj = Book.objects.filter(bid=i).first()
    #book_obj.authors.add(2, 4)

views.py

from django.shortcuts importrender, HttpResponse, redirect, reverse
from django.contrib importauth
from app01.myforms import *
from django.contrib.auth.decorators importlogin_required
from django.contrib.auth.models importUser
from app01.models import *
from django.core.paginator importPaginator, EmptyPage
#Create your views here.
FLAG =False


defregister(request):
    form_obj =Myreg()
    if request.method == "POST":
        form_obj =Myreg(request.POST)
        ifform_obj.is_valid():
            if not User.objects.filter(username=request.POST.get("username")).first():
                User.objects.create_user(
                    username=request.POST.get("username"),
                    email=request.POST.get("user_email"),
                    password=request.POST.get("password"),
                )
                globalFLAG
                FLAG =True
                return redirect("/login/")
            else:
                title = "swal('注册用户已存在...')"
    return render(request, "reg.html", locals())


deflogin(request):
    form_obj =Mylogin()
    globalFLAG
    ifFLAG:
        title = "swal('注册成功...')"
    else:
        title = ""target_url = request.GET.get("next", "/index/")
    if request.method == "POST":
        form_obj =Mylogin(request.POST)
        ifform_obj.is_valid():
            username = request.POST.get("username")
            password = request.POST.get("password")
            user =auth.authenticate(
                request,
                username=username,
                password=password,
            )
            if user is notNone:
                auth.login(request, user)
                returnredirect(target_url)
    FLAG =False
    return render(request, "login.html", locals())


@login_required
defindex(request):
    authors = Author.objects.all().order_by("aid")
    publishs = Publish.objects.all().order_by("pid")
    book_obj = Book.objects.all().order_by("bid")
    paginator_obj = Paginator(book_obj, 10)
    page_num = int(request.GET.get("page", 1))
    try:
        current_page =paginator_obj.page(page_num)
    exceptEmptyPage as e:
        current_page = paginator_obj.page(1)
    if paginator_obj.num_pages > 11:
        if page_num-5 < 1:
            page_range = range(1, 12)
        elif page_num+5 >paginator_obj.num_pages:
            page_range = range(paginator_obj.num_pages-10, paginator_obj.num_pages+1)
        else:
            page_range = range(page_num-5, page_num+6)
    else:
        page_range = range(1, paginator_obj.num_pages+1)
    return render(request, "index.html", locals())


@login_required
defadd_book(request):
    authors = Author.objects.all().order_by("aid")
    publishs = Publish.objects.all().order_by("pid")
    form_obj =AddBook()
    if request.method == "POST":
        form_obj =AddBook(request.POST)
        ifform_obj.is_valid():
            book_obj =Book.objects.create(
                book_name=request.POST.get("book_name"),
                book_price=request.POST.get("book_price"),
                book_date=request.POST.get("book_date"),
                publish_id=request.POST.get("publish_id"),
            )
            author_list = request.POST.getlist("author_id")
            book_obj.authors.add(*author_list)
            return redirect("/index/")
    return render(request, "add_book.html", locals())


@login_required
defdelete_book(request, number, page):
    Book.objects.filter(bid=number).delete()
    book_obj = Book.objects.all().order_by("bid")
    paginator_obj = Paginator(book_obj, 10)
    if page not inpaginator_obj.page_range:
        page -= 1url = "/index/?page=%s" %page
    returnHttpResponse(url)


@login_required
defedit_book(request, number, page):
    print(request.path_info)
    book_obj = Book.objects.filter(bid=number).first()
    ifrequest.is_ajax():
        Book.objects.filter(bid=number).update(
            book_price=request.POST.get("book_price"),
            book_date=request.POST.get("book_date"),
            publish_id=int(request.POST.get("publish_id")),
        )
        authors_id = request.POST.getlist("authors_id[]")
        book_obj.authors.set(authors_id)
        url = "/index/?page=%s" %page
        returnHttpResponse(url)


@login_required
defshow_publish(request, number):
    publish_obj = Publish.objects.filter(pid=number).first()
    books_obj = Publish.objects.filter(pid=number).values_list(
        "book__book_name",
        "book__book_price",
        "book__book_date",
    ).order_by('pid')
    paginator_obj = Paginator(books_obj, 10)
    page_num = int(request.GET.get("page", 1))
    try:
        current_page =paginator_obj.page(page_num)
    exceptEmptyPage as e:
        current_page = paginator_obj.page(1)
    if paginator_obj.num_pages > 11:
        if page_num-5 < 1:
            page_range = range(1, 12)
        elif page_num+5 >paginator_obj.num_pages:
            page_range = range(paginator_obj.num_pages-10, paginator_obj.num_pages+1)
        else:
            page_range = range(page_num-5, page_num+6)
    else:
        page_range = range(1, paginator_obj.num_pages+1)
    if request.method == "POST":
        Publish.objects.filter(pid=number).update(
            pub_name=request.POST.get("pub_name"),
            pub_addr=request.POST.get("pub_addr"),
            pub_email=request.POST.get("pub_email"),
        )
        url = reverse("app01_show_publish", args=(number,))
        returnredirect(url)
    return render(request, "show_publish.html", locals())


@login_required
defadd_publish(request):
    if request.method == "POST":
        if request.POST.get("pub_name") and request.POST.get("pub_addr") and request.POST.get("pub_email"):
            publish_obj =Publish.objects.create(
                pub_name=request.POST.get("pub_name"),
                pub_addr=request.POST.get("pub_addr"),
                pub_email=request.POST.get("pub_email"),
            )
            ifpublish_obj:
                return redirect("/index/")
    return render(request, "add_publish.html", locals())


@login_required
defdel_publish(request, name):
    Publish.objects.filter(pub_name=name).delete()
    return redirect("/index/")


@login_required
defshow_author(request, number):
    author_obj = Author.objects.filter(aid=number).first()
    book_obj = Author.objects.filter(aid=number).values_list(
        "book__book_name",
        "book__book_price",
        "book__book_date",
    ).order_by('aid')
    paginator_obj = Paginator(book_obj, 10)
    page_num = int(request.GET.get("page", 1))
    try:
        current_page =paginator_obj.page(page_num)
    exceptEmptyPage as e:
        current_page = paginator_obj.page(1)
    if paginator_obj.num_pages > 11:
        if page_num-5 < 1:
            page_range = range(1, 12)
        elif page_num+5 >paginator_obj.num_pages:
            page_range = range(paginator_obj.num_pages-10, paginator_obj.num_pages+1)
        else:
            page_range = range(page_num-5, page_num+6)
    else:
        page_range = range(1, paginator_obj.num_pages+1)
    if request.method == "POST":
        Author.objects.filter(aid=number).update(
            author_name=request.POST.get("author_name"),
        )
        url = reverse("app01_show_author", args=(number,))
        returnredirect(url)
    return render(request, "show_author.html", locals())


@login_required
defadd_author(request):
    if request.method == "POST":
        if request.POST.get("author_name"):
            try:
                author_obj =Author.objects.create(
                    author_name=request.POST.get("author_name"),
                )
                ifauthor_obj:
                    return redirect("/index/")
            exceptException as e:
                title = "swal('该作者已存在...')"
    return render(request, "add_author.html", locals())


@login_required
defdel_author(request, name):
    Author.objects.filter(author_name=name).delete()
    return redirect("/index/")


@login_required
deflogout(request):
    auth.logout(request)
    return redirect("/login/")


@login_required
defset_password(request):
    form_obj =SetPassword()
    user =request.user
    if request.method == "POST":
        form_obj =SetPassword(request.POST)
        ifform_obj.is_valid():
            old_password = request.POST.get("old_password")
            new_password = request.POST.get("new_password")
            confirm_password = request.POST.get("confirm_password")
            ifuser.check_password(old_password):
                user.set_password(new_password)
                user.save()
                return redirect("/login/")
            else:
                title = "swal('原密码输入错误...')"
    return render(request, "set_password.html", locals())

six_module_one_work文件夹

__init__.py

importpymysql

pymysql.install_as_MySQLdb()

settings.py

DATABASES ={
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '2021122101',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': '123456',
    }
}

STATICFILES_DIRS =[
    os.path.join(BASE_DIR, "static"),
]

LOGIN_URL = "/login/"

urls.py

from django.contrib importadmin
from django.urls importpath
from app01 importviews

urlpatterns =[
    path('admin/', admin.site.urls),
    path("login/", views.login, name="app01_login"),
    path("reg/", views.register, name="app01_reg"),
    path("index/", views.index, name="app01_index"),
    path("add_book/", views.add_book, name="app01_add_book"),
    path("delete_book/<int:number>/<int:page>/", views.delete_book, name="app01_delete_book"),
    path("edit_book/<int:number>/<int:page>/", views.edit_book, name="app01_edit_book"),
    path("show_publish/<int:number>/", views.show_publish, name="app01_show_publish"),
    path("add_publish/", views.add_publish, name="app01_add_publish"),
    path("del_publish/<str:name>/", views.del_publish, name="app01_del_publish"),
    path("show_author/<int:number>/", views.show_author, name="app01_show_author"),
    path("add_author/", views.add_author, name="app01_add_author"),
    path("del_author/<str:name>/", views.del_author, name="app01_del_author"),
    path("logout/", views.logout, name="app01_logout"),
    path("set_password/", views.set_password, name="app01_set_password"),
    path("", views.login),
]

templates文件夹

add_author.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
    <link rel="stylesheet"href="{% static 'sweetalert/sweetalert.css' %}">
    <script src="{% static 'sweetalert/sweetalert.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3>添加作者</h3>
            <a href="{% url 'app01_index' %}"class="pull-right"><button class="btn btn-primary">首页</button></a>
            <br><br>
            <form action=""method="post">{% csrf_token %}
                <p>作者姓名:
                    <input type="text"name="author_name"class="form-control">
                </p>
                <p>
                    <input type="submit"class="btn btn-block btn-info">
                </p>
            </form>
        </div>
    </div>
</div>
<script>{{ title|safe }}
</script>
</body>
</html>

add_book.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3 class="text-center">添加书籍</h3>
            <a href="{% url 'app01_index' %}"class="pull-right"><button class="btn btn-primary">首页</button></a>
            <br><br>
            <form action=""method="post"novalidate>{% csrf_token %}
                <p>书籍名称:
                    <input type="text"name="book_name"class="form-control">
                    <span style="color: red">{{ form_obj.book_name.errors.0 }}</span>
                </p>
                <p>书籍价格:
                    <input type="text"name="book_price"class="form-control">
                    <span style="color: red">{{ form_obj.book_price.errors.0 }}</span>
                </p>
                <p>出版日期:
                    <input type="date"name="book_date"class="form-control">
                </p>
                <p>出版社:
                    <select name="publish_id"id=""class="form-control">{% for publish in publishs %}
                            <option value="{{ publish.pk }}">{{ publish.pub_name }}</option>{% endfor %}
                    </select>
                </p>
                <p>作者:
                    <select name="author_id"id=""class="form-control"multiple>{% for author in authors %}
                            <option value="{{ author.pk }}">{{ author.author_name }}</option>{% endfor %}
                    </select>
                </p>
                <input type="submit"value="添加"class="btn btn-success btn-block">
            </form>
        </div>
    </div>
</div>
</body>
</html>

add_publish.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3>添加出版社</h3>
            <a href="{% url 'app01_index' %}"class="pull-right"><button class="btn btn-primary">首页</button></a>
            <br><br>
            <form action=""method="post">{% csrf_token %}
                <p>出版社名称:
                    <input type="text"name="pub_name"class="form-control">
                </p>
                <p>出版社地址:
                    <input type="text"name="pub_addr"class="form-control">
                </p>
                <p>出版社邮箱:
                    <input type="text"name="pub_email"class="form-control">
                </p>
                <p>
                    <input type="submit"value="添加"class="btn btn-info btn-block">
                </p>
            </form>
        </div>
    </div>
</div>
</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
    <link rel="stylesheet"href="{% static 'sweetalert/sweetalert.css' %}">
    <script src="{% static 'sweetalert/sweetalert.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <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="#">Brand</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="#">Link <span class="sr-only">(current)</span></a></li>
                        <li><a href="#">Link</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="#">Link</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>
                            </ul>
                        </li>
                    </ul>
                </div><!--/.navbar-collapse -->
            </div><!--/.container-fluid -->
        </nav>
        <div class="row">
                <a href="{% url 'app01_logout' %}">
                    <button class="btn btn-danger pull-left">退出</button>
                </a>
                &nbsp;
                <a href="{% url 'app01_set_password' %}">
                    <button class="btn btn-success">修改密码</button>
                </a>
                <a href="{% url 'app01_add_book' %}">
                    <button class="btn btn-primary pull-right">添加书籍</button>
                </a>
                <br><br><br>
                <table class="table table-bordered table-striped table-condensed">
                    <thead>
                    <tr>
                        <th class="text-center">序号</th>
                        <th class="text-center">书籍名称</th>
                        <th class="text-center">书籍价格</th>
                        <th class="text-center">出版日期</th>
                        <th class="text-center">出版社</th>
                        <th class="text-center">作者</th>
                        <th class="text-center">操作</th>
                    </tr>
                    </thead>
                    <tbody>{% for book in current_page %}
                        <tr class="text-center">
                            <td>{% if forloop.first %}
                                    {{ current_page.start_index }}
                                {% else %}
                                    {{ current_page.start_index|add:forloop.counter0 }}
                                {% endif %}
                            </td>
                            <td>{{ book.book_name }}</td>
                            <td>{{ book.book_price }}</td>
                            <td>{{ book.book_date|date:'Y-m-d' }}</td>
                            <td><a href="{% url 'app01_show_publish' book.publish.pid %}">{{ book.publish.pub_name }}</a></td>
                            <td>{% for author in book.authors.all %}
                                    {% if forloop.last %}
                                        <a href="{% url 'app01_show_author' author.aid %}"target="_blank">{{ author.author_name }}</a>{% else %}
                                        <a href="{% url 'app01_show_author' author.aid %}"target="_blank">{{ author.author_name }},</a>{% endif %}
                                {% endfor %}
                            </td>
                            <td>
                                <button class="btn btn-danger btn-xs b2"number_01="{{ book.pk }}" >编辑</button>
                                <button class="btn btn-warning btn-xs b1"number={{ book.pk }}>删除</button>
                            </td>
                        </tr>{% endfor %}
                    <select name=""id="i6"style="display: none">{% for publish in publishs %}
                            <option value={{ publish.pid }}>{{ publish.pub_name }}</option>{% endfor %}
                    </select>
                    <select name=""id="i7"style="display: none"multiple>{% for author in authors %}
                            <option value={{ author.pk }}>{{ author.author_name }}</option>{% endfor %}
                    </select>
                    </tbody>
                </table>
                <nav aria-label="Page navigation"class="text-center">
                    <ul class="pagination">
                        <li>
                            <a href="?page=1"aria-label="Previous">
                                <span aria-hidden="true">首页</span>
                            </a>
                        </li>{% if current_page.has_previous %}
                            <li>
                                <a href="?page={{ current_page.previous_page_number }}"aria-label="Previous">
                                    <span aria-hidden="true">&laquo;</span>
                                </a>
                            </li>{% else %}
                            <li class="disabled">
                                <span aria-hidden="true">&laquo;</span>
                            </li>{% endif %}
                        {% for page in page_range %}
                            {% if page == page_num %}
                                <li class="active"><a href="?page={{ page }}">{{ page }}</a></li>{% else %}
                                <li><a href="?page={{ page }}">{{ page }}</a></li>{% endif %}
                        {% endfor %}
                        {% if current_page.has_next %}
                            <li>
                                <a href="?page={{ current_page.next_page_number }}"aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>{% else %}
                            <li class="disabled">
                                <span aria-hidden="true">&raquo;</span>
                            </li>{% endif %}
                        <li>
                            <a href="?page={{ paginator_obj.num_pages }}"aria-label="Previous">
                                <span aria-hidden="true">尾页</span>
                            </a>
                        </li>
                    </ul>
                </nav>

                <!--Modal -->
                <div class="modal fade"id="myModal"tabindex="-1"role="dialog"aria-labelledby="myModalLabel">
                    <div class="modal-dialog"role="document">
                        <div class="modal-content">
                            <div class="modal-header">
                                <button type="button"class="close"data-dismiss="modal"aria-label="Close"><span
                                        aria-hidden="true">&times;</span></button>
                                <h4 class="modal-title"id="myModalLabel">编辑书籍</h4>
                            </div>
                            <div class="modal-body">
                                <p>书籍名称:
                                    <input type="text"name="book_name"class="form-control"id="i1"disabled>
                                </p>
                                <p>书籍价格:
                                    <input type="text"name="book_price"class="form-control"id="i2">
                                </p>
                                <p>出版日期:
                                    <input type="date"name="book_date"class="form-control"id="i3">
                                </p>
                                <p>出版社:
                                    <select name="publish_id"id="i4"class="form-control">
                                    </select>
                                </p>
                                <p>作者:
                                    <select name="authors_id"id="i5"class="form-control"multiple>
                                    </select>
                                </p>
                            </div>
                            <div class="modal-footer">
                                <button type="button"class="btn btn-default"data-dismiss="modal">取消</button>
                                <button type="button"class="btn btn-primary b3">保存</button>
                            </div>
                        </div>
                    </div>
                </div>
        </div>
    </div>
</div>

<script>$(".b1").click(function() {
        let number =$(this).attr("number");
        swal({
                title: "确定要删除吗?",
                text: "删除后书籍就没有了!",
                type: "warning",
                showCancelButton: true,
                confirmButtonClass: "btn-danger",
                confirmButtonText: "确定!",
                cancelButtonText: "取消!",
                closeOnConfirm: false,
                closeOnCancel: false},
            function(isConfirm) {
                if(isConfirm) {
                    $.ajax({
                        url: '/delete_book/' +number + '/{{ page_num }}/',
                        type: "post",
                        data: {'csrfmiddlewaretoken': '{{ csrf_token }}'},
                        success: function(data) {
                            setTimeout(function() {
                                location.href =data;
                            }, 3000);
                        }
                    });
                    swal("Deleted!", "您已成功删除该书籍", "success");
                } else{
                    swal("Cancelled", "您已取消删除该书籍", "error");
                }
            })
    })
    $(".b2").click(function() {
        $('#myModal').modal('show');

        let value1 =$(this).parentsUntil("tbody").children('td').eq(1).html();
        let value2 =$(this).parentsUntil("tbody").children('td').eq(2).html();
        let value3 =$(this).parentsUntil("tbody").children('td').eq(3).html();
        let value_10 =$(this).parentsUntil("tbody").children("td").eq(4).children('a').html();
        let value_11 =$(this).parentsUntil("tbody").children("td").eq(5).children("a");

        $("#i1").val(value1);
        $("#i2").val(value2);
        $("#i3").val(value3);

        let value4 =$("#i6").children();
        $(value4).each(function() {
            $("#i4").append($(this));
        })
        $("#i4").children().each(function() {
            if($(this).html() ===value_10) {
                $(this).prop("selected", true);
            }
        })

        let value5 =$("#i7").children();
        $(value5).each(function() {
            $("#i5").append($(this));
        })
        let array = newArray();
        $(value_11).each(function() {
            let ss =$(this).html().split(',')[0];
            array.push(ss);
        })
        $.each(array, function(index, value) {
            $("#i5").children("option").each(function() {
                if($(this).html() ===value) {
                    $(this).prop("selected", true);
                }
            })
        })

        let number =$(this).attr("number_01");
        $(".b3").attr("number_02", number);
    })
    $(".b3").click(function() {
        let book_name =$("#i1").val();
        let book_price =$("#i2").val();
        let book_date =$("#i3").val();
        let publish_id =$("#i4").val();
        let authors_id =$("#i5").val();
        let number =$(this).attr("number_02");
        $.ajax({
            url: '/edit_book/' +number + '/{{ page_num }}/',
            type: "post",
            data: {
                'csrfmiddlewaretoken': '{{ csrf_token }}',
                'book_name': book_name,
                'book_price': book_price,
                'book_date': book_date,
                'publish_id': publish_id,
                'authors_id': authors_id,
            },
            success: function(data) {
                setTimeout(function() {
                    {#location.href =data;#}
                    window.location.reload();
                }, 2000);
            }
        })
        swal("modify successfully!", "您已成功修改该书籍", "success");
        $('#myModal').modal('hide');
    })
</script>
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
    <link rel="stylesheet"href="{% static 'sweetalert/sweetalert.css' %}">
    <script src="{% static 'sweetalert/sweetalert.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3 class="text-center text-danger">登录</h3>
            <form action=""method="post"novalidate>{% csrf_token %}
                {% for form in form_obj %}
                <p>{{ form.label }}: {{ form }}
                <span style="color: red">{{ form.errors.0 }}</span>
                </p>{% endfor %}
                <input type="submit"value="登录"class="btn btn-block btn-primary">
            </form>
            <p class="pull-right">
                <span class="text-danger">没有账号?</span>
                <a href="{% url 'app01_reg' %}">点击注册</a>
            </p>
        </div>
    </div>
</div>
<script>{{ title|safe }}</script>
</body>
</html>

reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
    <link rel="stylesheet"href="{% static 'sweetalert/sweetalert.css' %}">
    <script src="{% static 'sweetalert/sweetalert.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3 class="text-center text-warning">注册</h3>
            <form action=""method="post"novalidate>{% csrf_token %}
                {% for form in form_obj %}
                <p>{{ form.label }}: {{ form }}
                <span style="color: red">{{ form.errors.0 }}</span>
                </p>{% endfor %}
                <input type="submit"value="注册"class="btn btn-primary btn-block">
            </form>
            <p class="pull-right">
                <span class="text-danger">已有账号?</span>
                <a href="{% url 'app01_login' %}">点击登录</a>
            </p>
        </div>
    </div>
</div>
<script>{{ title|safe }}</script>
</body>
</html>

set_password.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
    <link rel="stylesheet"href="{% static 'sweetalert/sweetalert.css' %}">
    <script src="{% static 'sweetalert/sweetalert.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3 class="text-danger text-center">修改密码</h3>
            <a href="{% url 'app01_index' %}">
                <button class="btn btn-primary pull-right">首页</button>
            </a>
            <br><br>
            <form action=""method="post"novalidate>{% csrf_token %}
                {% for form in form_obj %}
                <p>{{ form.label }}: {{ form }}
                    <span style="color: red">{{ form.errors.0 }}</span>
                </p>{% endfor %}
                <p>
                    <input type="submit"class="btn btn-success btn-block">
                </p>
            </form>
        </div>
    </div>
</div>
<script>{{ title|safe }}
</script>
</body>
</html>

show_author.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3 class="text-center">作者信息及所出版书籍</h3>
            <a href="{% url 'app01_index' %}"class="pull-right"><button class="btn btn-primary">首页</button></a>
            <a href="{% url 'app01_add_author' %}"class="pull-left"><button class="btn btn-danger">添加作者</button></a>
            &nbsp;
            <a href="{% url 'app01_del_author' author_obj.author_name %}"><button class="btn btn-warning">删除作者</button></a>
            <form action=""method="post">{% csrf_token %}
                <br><br>
                <p>作者姓名:
                    <input type="text"name="author_name"class="form-control"value="{{ author_obj.author_name }}">
                </p>
                <p>
                    <input type="submit"value="更改"class="btn btn-block btn-info">
                </p>
            </form>
            <table class="table table-bordered table-hover table-condensed">
                <thead>
                <tr>
                    <th class="text-center">书籍名称</th>
                    <th class="text-center">书籍价格</th>
                    <th class="text-center">出版日期</th>
                </tr>
                </thead>
                <tbody>{% for book in current_page %}
                <tr class="text-center">
                <td>{{ book.0 }}</td>
                <td>{{ book.1 }}</td>
                <td>{{ book.2|date:'Y-m-d' }}</td>
                </tr>{% endfor %}
                </tbody>
            </table>
            <nav aria-label="Page navigation"class="text-center">
                <ul class="pagination">{% if current_page.has_previous %}
                        <li>
                            <a href="?page={{ current_page.previous_page_number }}"aria-label="Previous">
                                <span aria-hidden="true">&laquo;</span>
                            </a>
                        </li>{% else %}
                        <li class="disabled">
                            <span aria-hidden="true">&laquo;</span>
                        </li>{% endif %}

                    {% for page in page_range %}
                        {% if page == page_num %}
                        <li class="active"><a href="?page={{ page }}">{{ page }}</a></li>{% else %}
                            <li><a href="?page={{ page }}">{{ page }}</a></li>{% endif %}
                    {% endfor %}

                    {% if current_page.has_next %}
                        <li>
                            <a href="?page={{ current_page.next_page_number }}"aria-label="Next">
                                <span aria-hidden="true">&raquo;</span>
                            </a>
                        </li>{% else %}
                        <li class="disabled">
                                <span aria-hidden="true">&raquo;</span>
                        </li>{% endif %}
                </ul>
            </nav>
        </div>
    </div>
</div>
</body>
</html>

show_publish.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>{% load static %}
    <script src="{% static 'jQuery3.6.js' %}"></script>
    <link rel="stylesheet"href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
                <h3 class="text-center">出版社信息及所出版书籍</h3>
                <a href="{% url 'app01_index' %}"class="pull-right"><button class="btn btn-primary">首页</button></a>
                <a href="{% url 'app01_add_publish' %}"class="pull-left"><button class="btn btn-danger">添加出版社</button></a>
                &nbsp;
                <a href="{% url 'app01_del_publish' publish_obj.pub_name %}"><button class="btn btn-warning">删除出版社</button></a>
            <form action=""method="post">{% csrf_token %}
                <br><br>
                <p>出版社名称:
                    <input type="text"name="pub_name"value="{{ publish_obj.pub_name }}"class="form-control">
                </p>
                <p>出版社地址:
                    <input type="text"name="pub_addr"value="{{ publish_obj.pub_addr }}"class="form-control">
                </p>
                <p>出版社邮箱:
                    <input type="text"name="pub_email"value="{{ publish_obj.pub_email }}"class="form-control">
                </p>
                <p>
                    <input type="submit"value="更改"class="btn btn-block btn-info">
                </p>
            </form>
            <table class="table table-bordered table-hover table-condensed">
                <thead>
                <tr>
                    <th class="text-center">书籍名称</th>
                    <th class="text-center">书籍价格</th>
                    <th class="text-center">出版日期</th>
                </tr>
                </thead>
                <tbody>{% for book in current_page %}
                    <tr class="text-center">
                        <td>{{ book.0 }}</td>
                        <td>{{ book.1 }}</td>
                        <td>{{ book.2|date:'Y-m-d' }}</td>
                    </tr>{% endfor %}
                </tbody>
            </table>
            <nav aria-label="Page navigation"class="text-center">
                <ul class="pagination">{% if current_page.has_previous %}
                        <li>
                            <a href="?page={{ current_page.previous_page_number }}"aria-label="Previous">
                                <span aria-hidden="true">&laquo;</span>
                            </a>
                        </li>{% else %}
                        <li class="disabled">
                            <span aria-hidden="true">&laquo;</span>
                        </li>{% endif %}

                    {% for page in page_range %}
                        {% if page == page_num %}
                        <li class="active"><a href="?page={{ page }}">{{ page }}</a></li>{% else %}
                            <li><a href="?page={{ page }}">{{ page }}</a></li>{% endif %}
                    {% endfor %}

                    {% if current_page.has_next %}
                        <li>
                            <a href="?page={{ current_page.next_page_number }}"aria-label="Next">
                                <span aria-hidden="true">&raquo;</span>
                            </a>
                        </li>{% else %}
                        <li class="disabled">
                                <span aria-hidden="true">&raquo;</span>
                        </li>{% endif %}
                </ul>
            </nav>
        </div>
    </div>
</div>
</body>
</html>

README.txt

"""环境配置:
        Django版本:2.0.1
        MySQL版本:5.7.35
        MySQL准备数据库:'2021122101'
        MySQL链接用户名及密码:'root'/'123456'

系统初始化数据:
        运行app01.tests.py中注释的代码即可
        初始化数据有系统初始登录账号及密码,作者/出版社/书籍/作者书籍关系这几张表数据

功能:
        项目启动后,首先进入登录页面,登录页面与注册页面各有a标签链接进行交互切换,注册成功后自动跳转到登陆页面;
        首页展示了书籍列表,可以对书籍进行添加、编辑、删除操作;出版社及作者均可进行点击查看,跳转到对应页面查看信息;
        点击出版社,页面会展示该出版社所出版的所有书籍,还可对出版社进行添加、编辑、删除操作;
        点击作者,弹出新页面,该页面展示该作者所关联的书籍信息,还可对作者进行添加、编辑、删除操作;
        首页点击退出,即退出登录回到登录页面;

        修改书籍信息,弹出模态框,模态框回显该书籍信息,且书籍名称不可编辑,点击模态框保存按钮发送Ajax请求;
        添加书籍信息,书籍名称不能重复;
        删除书籍,均有二次确认操作;
"""

如何一次性将项目所依赖的三方库版本信息导入及导出?

"""pycharm中的命令行输入如下命令即可:

生成requirements.txt文件:pip freeze > requirements.txt

安装requirements.txt依赖:pip install -r requirements.txt
"""

"""requirements.txt导出信息展示 certifi==2021.5.30 charset-normalizer==2.0.4 click==8.0.1 colorama==0.4.4 DBUtils==2.0.2 decorator==4.4.2 Django==2.0.1 et-xmlfile==1.1.0 Flask==2.0.1 idna==3.2 imageio==2.9.0 imageio-ffmpeg==0.4.5 itsdangerous==2.0.1 Jinja2==3.0.1 MarkupSafe==2.0.1 moviepy==1.0.3 numpy==1.21.2 openpyxl==3.0.7 Pillow==8.3.2 prettytable==2.2.0 proglog==0.1.9 PyMySQL==1.0.2 pytz==2021.3 requests==2.26.0 tqdm==4.62.2 urllib3==1.26.6 wcwidth==0.2.5 Werkzeug==2.0.1 """

该程序已发现的小BUG

"""编辑书籍信息的模态框,选择作者是多选的下拉框,没有给模态框的取消按钮绑定点击事件,所以当重新选择了作者后点击取消按钮,此时再次点击书籍编辑按钮弹出模态框时,作者的默认选中标签信息与书籍的作者信息不相符。

解决方案:给模态框的取消按钮及右上角关闭按钮都绑定同一个事件,即把作者的多选下拉框的子标签option标签的默认选中属性都取消?
"""

免责声明:文章转载自《开发一个简易的图书增删改查页面》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇RK Android7.1 使用POWER按键才能开机[Android进阶]Binder学习(初始篇)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Django(多表查询操作)

首先了解一下 mysql中的表之间的关系,一对一,一对多,多对一,多对多。 一对多关系、多对一关系、一对一关系 至少都有一侧是单个实体,所以记录之间的联系通过外键实现,让外键指向这个实体。 实现这种关系时,要在“多”这一侧加入一个外键,指向“一”这一侧联接的记录。 多对多关系 解决方法是添加第三个表,这个表称为关联表。 多对多关系可以分解成原表和关联...

Document节点

概述 document节点对象代表整个文档,每张网页都有自己的document对象。window.document属性就指向这个对象。只要浏览器开始载入 HTML 文档,该对象就存在了,可以直接使用。 document对象有不同的办法可以获取。 正常的网页,直接使用document或window.document。 iframe框架里面的网页,使用ifr...

Html代码中table跨2行和跨2列的用法

一直以来总是会写跨2列的Html代码,不会写跨2行的例子,找机会研究了一下!先说说跨2列的例子,这个很好理解例1  跨2列: 1<table border="1">2                <tr>3                    <td colspan="2" align="center">111<...

el-upload 上传表单验证

<template> <div> <div class="container"> <el-form style="60%;" :model="form" status-icon :rules="rules" re...

##Jquery基础(三)

Jquery基础-DOM ##一、DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。 浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组...

移动端页面开发适配 rem布局原理

主题 HTML移动端页面开发适配 rem布局原理 什么是适配,为什么要适配 我们拿到的设计图一般是以640,750,1080分辨率为基准设计的,而现在的手机终端各式各样,分辨率不同,逻辑像素不同 ,适口不同,所以为了让我们的页面在每个设备上都可以良好的展示,那么就需要为这些设备做统一的处理,这个过程就称为移动端适配。 需要知道的一些概念: 物理像素(phy...