6.1-图书增删改查页面(代码片段)

Alice的小屋 Alice的小屋     2022-11-18     719

关键词:

一、需求及注意事项

需求:
1.列出图书列表、出版社列表、作者列表
2.点击作者,会列出其出版的图书列表
3.点击出版社,会列出其下的图书列表
4.可以创建、修改、删除 图书、作者、出版社

完成及注意事项:
1.注册
/register/
2.登录
/login/
3.注销
/logout/
4.图书列表
/book_list/
/add_book/
/update_book/303/
/del_book/
5.出版社列表
/publisher_list/
/add_publisher/
/update_publisher/105/
/update_book/306/105/publisher/ # 通过出版社,修改该书,之后返回出版社页面
/del_publisher/
/book_list/105/publisher/ # 通过出版社,查看该出版社得图书列表
/add_book/105/publisher/ # 通过出版社,增加该出版社得某本书
/del_book/105/publisher/ # 通过出版社,删除该出版社得某本书
6.作者列表
/author_list/
/add_author/
/update_author/67/
/update_book/307/67/author/ # 通过作者,修改该书,之后返回作者页面
/del_author/
/book_list/67/author/ # 通过作者,查看该作者得图书列表
/add_book/67/author/ # 通过作者,增加该作者得某本书
/del_book/67/author/ # 通过作者,删除该作者得某本书

7.验证是否登录(session),跳转到之前访问得页面:
采用中间件 mymiddleware.py
def process_request(self,request):pass
白名单 黑名单

8.验证是否登录,装饰器!
def check_login(func):pass
最后采用中间件,
否则每一个函数都有要加装饰器。(@check_login)

9.批量插入测试数据
脚本 myscript.py
models.Book.objects.bulk_create(ret1)

10.自定义分页器
mypage.py
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
封装
上一页,下一页,首页,尾页

11.模板继承
base.html
% extends \'base.html\' %
block.super 可以引用基类模板的内容

12.静态文件
jquery-3.2.1.js
bootstrap-3.3.7

ajax发送post请求时
init_ajax.js
取 csrf token 的值发送

删除,页面得模态框 插件
sweetalert

13.settings配置文件
中间件
mysql

终端打印sql语句

logging
登录注册,会有日志记录

14.自定义过滤器和标签
templatetags/my_tag_filter.py
% load my_tag_filter %
path|update_path:book.id

15.urls
分发,名称空间,有名分组,反向解析
re_path(r\'^update_book/(?P<id>\\d+)\',views.update_book),
正则反向解析,需要赋值
return redirect(reverse(\'book:book_publisher\',args=(type_id,)))

16.FBV CBV
FBV(function base views) 视图里使用函数处理请求
CBV(class base views) 视图里使用类处理请求

path(\'login/\',views.LoginView.as_view(), name = \'login\')
class LoginView(View):pass
给CBV加装饰器:
@method_decorator(check_login)
def dispatch(self, request, *args, **kwargs):pass

17.表单forms组件
myforms.py

为forms组件赋初值
https://docs.djangoproject.com/en/2.0/ref/forms/api/
publisher_form.initial = \'name\':publisher.name

表单控件
给每一个key添加样式
def __init__(self,*args,**kwargs):pass
select下拉框:新增加的出版社,想不重启,立刻就显示:
def __init__(self,*args,**kwargs):pass
新增加书时,选择新增加的出版社
不能立刻通过校验is_valid 需要等一会,就通过了

18.DateTimeField
    注意点:
      TIME_ZONE = \'Asia/Shanghai\'
      USE_TZ = False

  https://blog.csdn.net/win_turn/article/details/53000770

    auto_now

auto_now_add
timezone

http://www.nanerbang.com/article/5488/
django:DateTimeField如何自动设置为当前时间并且能被修改:

DateTimeField.auto_now 如果为true 无法赋值,每次更新为最新时间;
DateTimeField.auto_now_add 如果为true 无法赋值,第一次创建时间

from django.db import models
import django.utils.timezone as timezone
class Doc(models.Model):
add_date = models.DateTimeField(\'保存日期\',default = timezone.now)
mod_date = models.DateTimeField(\'最后修改日期\', auto_now = True)

19.ORM表关系
一对一,(author authordetail)
删除author时,应该删除authordetail,关联的author就被删除了!

一对多,(book publisher)
删除出版社下面的某本书,拿到书的id,删除这本书;

多对多,(book author)
清除绑定关系,不应该删除书;

启动:
配置sql
python manage.py makemigrations
python manage.py migrate


详情:
需查看代码!!

二、数据库

三、页面效果

 

 

 

四、主要代码

 

 

urls.py

from django.urls import path,re_path

from book import views

urlpatterns = [
    # path(\'login/\',views.login, name = \'login\'),                 # FBV
    path(\'login/\',views.LoginView.as_view(), name = \'login\'),     # CBV
    # path(\'register/\',views.register, name = \'register\'),
    path(\'register/\',views.RegisterView.as_view(), name = \'register\'),
    path(\'exist_user/\',views.exist_user),
    path(\'logout/\',views.logout),

    path(\'book_list/\',views.book_list, name = \'book_list\'),
    # re_path(r\'^book_list/(\\d+)/(publisher)\',views.book_list),
    re_path(r\'^book_list/(?P<field_id>\\d+)/(?P<field_type>publisher)\',views.book_list),  # 有名分组
    # re_path(r\'^book_list/(\\d+)/(author)\',views.book_list),
    re_path(r\'^book_list/(?P<field_id>\\d+)/(?P<field_type>author)\',views.book_list),     # 有名分组

    path(\'del_book/\',views.del_book, name = \'del_book\'),
    re_path(r\'^del_book/(\\d+)/(publisher)\',views.del_book),
    re_path(r\'^del_book/(\\d+)/(author)\',views.del_book),

    path(\'add_book/\',views.add_book,name=\'add_book\'),
    re_path(r\'^add_book/(\\d+)/(publisher)\',views.add_book),
    re_path(r\'^add_book/(\\d+)/(author)\',views.add_book),

    re_path(r\'^update_book/(?P<book_id>\\d+)/(?P<field_id>\\d+)/(?P<field_type>publisher)\',views.update_book),
    re_path(r\'^update_book/(?P<book_id>\\d+)/(?P<field_id>\\d+)/(?P<field_type>author)\',views.update_book),
    re_path(r\'^update_book/(?P<book_id>\\d+)\',views.update_book),
    # 这个得放到下面 否则会截走 上面两个 因为第一个也是正则

    path(\'publisher_list/\',views.publisher_list, name = \'publisher_list\'),
    path(\'del_publisher/\',views.del_publisher, name = \'del_publisher\'),
    path(\'add_publisher/\',views.add_publisher, name = \'add_publisher\'),
    re_path(r\'^update_publisher/(\\d+)\',views.update_publisher),

    path(\'author_list/\',views.author_list, name = \'author_list\'),
    path(\'del_author/\',views.del_author, name = \'del_author\'),
    path(\'add_author/\',views.add_author, name = \'add_author\'),
    re_path(r\'^update_author/(\\d+)\',views.update_author),

]

 

models.py

from django.db import models
from django.utils import timezone


# 出版社类
class Publisher(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name


# 书类
class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish_date = models.DateTimeField(default=timezone.now())
    # 书只能关联一个出版社, 外键通常建在多的那一边
    publisher = models.ForeignKey(to=\'Publisher\',on_delete=models.CASCADE)

    def __str__(self):
        return self.title


# 作者类
class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    # 多对多, 建在哪边都可以
    books = models.ManyToManyField(to=\'Book\',related_name=\'authors\')

    detail = models.OneToOneField(to=\'AuthorDetail\',null=True,on_delete=models.CASCADE)

    def __str__(self):
        return self.name


# 作者详情
class AuthorDetail(models.Model):
    age = models.IntegerField()
    addr = models.TextField()


# 登录注册的用户信息
class UserInfo(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    pwd = models.CharField(max_length=32)

 

myforms.py

# -*- coding:utf-8 -*-
from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError

from book import models

widget_input = widgets.TextInput(attrs=\'class\':\'form-control\')
widg_num = widgets.NumberInput(attrs=\'class\':\'form-control\')
widget_password = widgets.PasswordInput(attrs=\'class\':\'form-control\')


class PublisherForm(forms.Form):
    name = forms.CharField(
        label=\'出版社名称\',
        min_length=4,
        max_length=32,
        error_messages=
            \'required\':\'不能为空\',
            \'min_length\':\'不能小于4位\',
        ,
        widget=widget_input
    )

    def clean_name(self):
        val = self.cleaned_data.get(\'name\')
        if not val.isdigit():
            return val
        else:
            raise ValidationError(\'名称不能是纯数字\')


class AuthorForm(forms.Form):
    name = forms.CharField(
        label=\'姓名\',
        min_length=2,
        max_length=16,
        error_messages=
            \'required\':\'不能为空\',
            \'min_length\':\'不能小于2位\',
        ,
        # widget = widget_input
    )
    age = forms.IntegerField(
        label=\'年龄\',
        min_value=1,
        max_value=150,
        error_messages=
            \'required\':\'不能为空\',
            \'invalid\':\'格式错误\',
            \'min_value\':\'不能小于1岁\',
            \'max_value\':\'不能大于100岁\',
        ,
        # widget = widget_input
    )
    addr = forms.CharField(
        label=\'地址\',
        min_length=2,
        max_length=32,
        error_messages=
            \'required\':\'不能为空\',
            \'min_length\':\'不能小于2位\'
        ,
        # widget=widget_input,

    )

    # 给每一个key 添加样式
    def __init__(self,*args,**kwargs):
        super(AuthorForm, self).__init__(*args,**kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update(
                \'class\':\'form-control\'
            )

    def clean_name(self):
        val = self.cleaned_data.get(\'name\')
        if not val.isdigit():
            return val
        else:
            raise ValidationError(\'姓名不能是纯数字\')

    def clean_addr(self):
        val = self.cleaned_data.get(\'addr\')
        if not val.isdigit():
            return val
        else:
            raise ValidationError(\'地址不能是纯数字\')


class BookForm(forms.Form):
    title = forms.CharField(
        label=\'书名称\',
        max_length=32,
        error_messages=
            \'required\':\'不能为空\',
        ,
        widget=widget_input
    )
    price = forms.DecimalField(
        label=\'价格\',
        max_digits=8,
        decimal_places=2,
        error_messages=
            \'required\':\'不能为空\',
            \'max_digits\':\'不能超过8位\',
        ,
        widget=widg_num
    )

    # 最后选择了自己去添加 select 。。。。。。

    # publisher = forms.ChoiceField(
    #     label=\'出版社\',
    #     # choices=((1,\'篮球\'),(2,\'足球\')),
    #     choices=models.Publisher.objects.all().values_list(\'id\',\'name\'),
    #     initial=1,
    #     widget=widgets.Select(attrs=\'class\':\'form-control\')
    # )
    #
    # # 可以不用重启 刷新就有新的数据
    # def __init__(self,*args,**kwargs):
    #     super(BookForm, self).__init__(*args,**kwargs)
    #     self.fields[\'publisher\'].widget.choices = models.Publisher.objects.all().values_list(\'id\',\'name\')

    def clean_title(self):
        val = self.cleaned_data.get(\'title\')
        if not val.isdigit():
            return val
        else:
            raise ValidationError(\'名称不能为纯数字\')

    def clean_price(self):
        val = self.cleaned_data.get(\'price\')
        if val < 0:
            raise ValidationError(\'价格不能为负数\')
        else:
            return val


class LoginForm(forms.Form):
    username = forms.CharField(
        label=\'用户名\',
        min_length=2,
        max_length=16,
        error_messages=
            \'required\':\'不能为空\',
            \'min_length\':\'不能小于2位\'
        ,
        widget=widget_input
    )
    password = forms.CharField(
        label=\'密码\',
        min_length=6,
        max_length=16,
        error_messages=
            \'required\':\'不能为空\',
            \'min_length\':\'不能小于6位\'
        ,
        widget=widget_password

    )

    def clean_username(self):
        val = self.cleaned_data.get(\'username\')
        if not val.isdigit():
            return val
        else:
            raise ValidationError(\'用户名不能是纯数字\')

 

views.py

from django.shortcuts import render,HttpResponse,redirect,reverse
from django.utils.decorators import method_decorator
from django.core import serializers
from django.views import View
import json
import datetime
import logging
from functools import wraps

from book import models
from book import myforms
from utils.mypage import MyPaginator
from utils.hash_pwd import salt_pwd

logger = logging.getLogger(__name__)
# 生成一个名为collect的实例
collect_logger = logging.getLogger(\'collect\')


def check_login(func):
    \'\'\'
    判断用户有没有登录得装饰器
    :param func:
    :return:
    \'\'\'
    @wraps(func)
    def inner(request,*args,**kwargs):
        # 拿到当前访问网址
        url = request.get_full_path()
        if request.session.get(\'user\'):
            return func(request,*args,**kwargs)
        else:
            return redirect(\'/login/?next=\'.format(url))

    return inner


# def login(request):
#     \'\'\'
#     登录
#     :param request:
#     :return:
#     \'\'\'
#     login_form = myforms.LoginForm()
#     return render(request,\'login.html\',\'login_form\':login_form)
#
#
# def register(request):
#     \'\'\'
#     注册
#     :param request:
#     :return:
#     \'\'\'
#     register_form = myforms.LoginForm()
#     return render(request,\'register.html\',\'register_form\':register_form)


class LoginView(View):
    \'\'\'
    CBV 登录视图
    \'\'\'

    def get(self,request):
        login_form = myforms.LoginForm()
        return render(request, \'login.html\', \'login_form\': login_form)

    def post(self,request):
        login_form = myforms.LoginForm(request.POST)
        if login_form.is_valid():
            username = login_form.cleaned_data.get(\'username\')
            password = login_form.cleaned_data.get(\'password\')
            password = salt_pwd(password, username)
            if models.UserInfo.objects.filter(name=username,pwd=password):
                # 设置session
                request.session[\'user\'] = username
                # request.session.set_expiry(1800) # 设置session得失效时间

                # 登录成功 写log
                logger.info(\'用户:\'+username+\' 登录成功\')

                next_url = request.GET.get(\'next\')
                if next_url:
                    return redirect(next_url)   # 跳转到之前访问得页面
                else:
                    return redirect(reverse(\'book:book_list\'))

            else:
                # 登录失败,写log
                logger.error(\'用户:\'+username+\' 登录时,用户名或密码错误\')

                return render(request, \'login.html\', \'login_form\': login_form,\'error_msg\':\'用户名或密码错误\')
        else:
            return render(request, \'login.html\', \'login_form\': login_form)


class RegisterView(View):
    \'\'\'
    CBV 注册视图
    \'\'\'
    # @method_decorator(check_login)  给cbv 加装饰器 逻辑上不应该加在这里,但可以验证装饰器加成功了
    def dispatch(self, request, *args, **kwargs):
        return super(RegisterView, self).dispatch(request,*args,**kwargs)

    def get(self,request):
        register_form = myforms.LoginForm()
        return render(request,\'register.html\',\'register_form\':register_form)

    查看详情  

6.1-图书管理系统(代码片段)

实现功能:book单表的增删改查    主要代码:models.pyfromdjango.dbimportmodelsclassBook(models.Model):id=models.AutoField(primary_key=True)title=models.CharField(max_length=32,unique=True)price=model 查看详情

ssm框架整合---完成对图书数据表的增删改查(代码片段)

....spring层5.springmvc6.查询书籍功能实现7.新增书籍实现8.修改图书信息9.删除图书信息10.查询图书信息1.先去创建数据表并且放入几条初始化数据--创建数据库CR 查看详情

图书管理系统-单表的增删改查(代码片段)

配置环境settings.py文件MIDDLEWARE=[‘django.middleware.security.SecurityMiddleware‘,‘django.contrib.sessions.middleware.SessionMiddleware‘,‘django.middleware.common.CommonMiddleware‘,#‘django.middleware.csrf.CsrfViewMiddleware‘,#暂时不用,注释掉‘django.contrib.auth.middl... 查看详情

asp.netcore打造一个简单的图书馆管理系统外借/阅览图书信息的增删改查(代码片段)

...文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作。本系列文章主要参考资料:微软文档:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windows《ProASP.NETMVC5》、《锋利的jQ... 查看详情

java全栈web网页技术:15.书城项目实战四:管理端图书的增删改查(后台)(代码片段)

1.需求澄清管理端图书管理页面【book_manager.jsp】页面原型如下:需要实现图书的添加、删除、修改、分页显示等操作2.前期准备2.1创建数据表bookscreateTABLEbooks(idINTPRIMARYKEYauto_increment,titlevarchar(50),authorVARCHAR(50),priceDOUBLE(10,2),sales... 查看详情

一起学vue:crud(增删改查)(代码片段)

...辑页面我们把这些用户信息保存到Todos的数组中,然后增删改查就在这个数组上进行:Todos:[Name:"遛狗",Name:"跑步"]我们在这里一共要实现TodoList.vue、TodoAdd.vue、TodoEdit.vue三个组件,分别 查看详情

vue实现数据的增删改查(代码片段)

...里,个人中心里的数据列表里,都会有对这些数据进行增删改查的操作。比如在管理员后台的用户列表里,我们可以录入新用户的信息,也可以对既有的用户信息进行修改。在vue中,我们更应该专注于对数据的操作和处理。比如... 查看详情

django---进阶7(代码片段)

目录图书管理的图书增删改查choices参数(数据库字段设计常见)MTV与MVC模型多对多三种创建方式Ajax小例子作业图书管理的图书增删改查fromdjango.shortcutsimportrender,redirect,HttpResponsefromapp01importmodels#Createyourviewshere.defhome(request):returnrender... 查看详情

springboot+vue+axios+bootstrap实现图书的增删改查功能(代码片段)

SpringBoot+Vue+Axios+BootStrap实现图书的增删改查功能由于是初学Vue、Axios,可能在界面和功能上存在着一些问题,但这些并不妨碍使用。如果有对编程感兴趣的朋友,可以试着做一做。这个由于是第一次做,... 查看详情

jeesite应用实战(数据增删改查)(代码片段)

...以运行以后,就可以进入开发模块了,我们先从数据的增删改查做起。一、页面效果很简单,涉及到的就是数据的增删改查。二、如何利用jeesite做呢?上面我们也看到了,功能很简单,那么怎么利用jeesite做呢?jeesite能给我们提... 查看详情

6.1-图书管理系统(代码片段)

实现功能:book单表的增删改查代码:model.pyfromdjango.dbimportmodels#Createyourmodelshere.classBook(models.Model):id=models.AutoField(primary_key=True)title=models.CharField(max_length=32)pub_date=models.DateField()price=models.DecimalField(max_digits=8,decimal_places=2)publish=models.... 查看详情

springboot小案例(登陆,增删改查)(代码片段)

...要功能:实现登陆拦截,然后进入主页面进行增删改查工作,开启Druid数据源,进行durid日志监控页面展示:代码编写:   目录结构:   导入依赖:  配置application.yml配置登陆拦截器以及开启dur... 查看详情

jsp登录注册代码(增删改查+网页+数据库)(代码片段)

目录一·登录注册代码以及效果doregister.jsp:注册信息弹框login.jsp:登录dologin.jsp:与数据库相连、存放登陆的用户index.jsp:主界面update.jsp:修改doup.jsp:修改页面(帮助)info.jsp:详情dodel.jsp:删除界面二·页面跳转的方式... 查看详情

shsql增删改查(代码片段)

查看详情

java增删改查(代码片段)

查看详情

微信小程序云开发—“增删改查综合案例(跳转页面)”(代码片段)

实际需求:1.能查看商品列表2.点击"商品列表"中的商品跳转到“商品详情页”大体步骤:1.商品列表页对应:/Pages/demo1/demo12.商品详情页对应:/Pages/demo1-1/demo1-1一、商品列表页(Pages/demo1/demo1)demo1.wxml<viewwx:for="lis... 查看详情

csharpef增删改查封装(代码片段)

查看详情