zoukankan      html  css  js  c++  java
  • ORM单表操作

    ORM简介

    • MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
    • ORM是“对象-关系-映射”的简称。(Object Relational Mapping,简称ORM)(将来会学一个sqlalchemy,是和他很像的,但是django的orm没有独立出来让别人去使用,虽然功能比sqlalchemy更强大,但是别人用不了)
    • 类对象--->sql--->pymysql--->mysql服务端--->磁盘,orm其实就是将类对象的语法翻译成sql语句的一个引擎,明白orm是什么了,剩下的就是怎么使用orm,怎么来写类对象关系语句。

        img

    总结

    1. MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的方便了我们开发
    2. ORM 是“对象-关系-映射”的简称。类名对应表名 字段对应属性
    3. orm就是将类对象的语法翻译成sql语句的一个引擎,
    

    单表操作

    创建表

    创建表3步曲

    第1步 数据库连接配置
    第2步 models.py文件中创建一个类 也就是写类的键表语句
    第3步执行同步指令 使其类语句转化为数据库可理解的语句
    

    第1步连接数据库前配置

    settings配置文件中
    自己先在数据库中创建库
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'cs',
            'USER':'root',
            'PASSWORD':'123',
            'HOST':'127.0.0.1',
            'PORT':3306,
        }
    }
    
    2 项目文件夹下的init文件中写上下面内容,用pymysql替换mysqldb
    因为django链接mysql默认使用的是mysqldb但其不支持py3.7所以不用
    import pymysql
    pymysql.install_as_MySQLdb()
    
    
    settings配置文件中将 USE_TZ 的值改为 False
        # USE_TZ = True
        USE_TZ = False  # 告诉mysql存储时间时按照当地时间来寸,不要用utc时间
    使用pycharm的数据库客户端的时候,时区问题要注意
    

    第2步 创建一个类语句

    models.py文件中创建一个类 同步指令会翻译成mysql语句
    UserInfo 是表名 
    models 固定写法
    models后面AutoField等是 字段  注意id字段不创建也可以,系统会自动创建
    括号里面的primary_key等是 属性
    
    
    创建学生表实列
    class UserInfo(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=10)
        bday = models.DateField()
        checked = models.BooleanField()
    

    第3步执行数据库同步指令

    第1种方式
    在 Terminal中执行
    python manage.py makemigrations  #生成记录,每次修改了models里面的内容或者添加了新的app,新的app里面写了models里面的内容,都要执行这两条
    python manage.py migrate         #执行上面这个语句的记录来创建表,生成的表名字前面会自带应用的名字,例如:你的book表在mysql里面叫做app01_book表
    
    第2种方式 带提示
    tool---Run manage.py Task....或Ctrl+Alt+R  调出提示环境
    执行 makemigrations 和 migrate  
    
    执行同步指令会在当前应用文件下下生成migrations文件夹
    
    注意
    每次修改了models里面的内容或者添加了新的app,新的app里面写了models里面的内容,都要执行这两条  添加字段的时候别忘了,该字段不能为空,所有要么给默认值,要么设置它允许为空null=True
    
    更多字段和参数
    <1> CharField
            字符串字段, 用于较短的字符串.
            CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
     
    <2> IntegerField
           #用于保存一个整数.
     
    <3> DecimalField
            一个浮点数 小数字段. 必须 提供两个参数:
            参数    描述
            max_digits    总位数(不包括小数点和符号)
            decimal_places    小数位数
                    举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                    models.DecimalField(..., max_digits=5, decimal_places=2)
    
     
    <4> AutoField
            一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段;
            自定义一个主键:my_id=models.AutoField(primary_key=True)
            如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.
     
    <5> BooleanField    bool字段
            A true/false field. admin 用 checkbox 来表示此类字段.
     
    <6> TextField
            一个容量很大的文本字段.
            admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
     
    <7> EmailField
            一个带有检查Email合法性的 CharField,不接受 maxlength 参数.
     
    <8> DateField
            一个日期字段. 共有下列额外的可选参数:
            Argument    描述
            auto_now    当对象被保存时(更新或者添加都行),自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
            auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
            (仅仅在admin中有意义...)
     
    <9> DateTimeField  一般用这个
             一个日期时间字段. 类似 DateField 支持同样的附加选项.
     
    <10> ImageField 图片·
            类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
            如果提供这两个参数,则图片将按提供的高度和宽度规格保存.    
            
    <11> FileField  文件
         一个文件上传字段.
         要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting,
         该格式将被上载文件的 date/time
         替换(so that uploaded files don't fill up the given directory).
         admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .
     
         注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
                (1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件.
                (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对
                 WEB服务器用户帐号是可写的.
                (2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
                 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).
                 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField
                 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.
     
    <12> URLField
          用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
          没有返回404响应).
          admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)
     
    <13> NullBooleanField
           类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
           admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.
     
    <14> SlugField
           "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
           若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
           以前的 Django 版本,没有任何办法改变50 这个长度.
           这暗示了 db_index=True.
           它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate
           the slug, via JavaScript,in the object's admin form: models.SlugField
           (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.
     
    <13> XMLField
            一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.
     
    <14> FilePathField
            可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
            参数    描述
            path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目.
            Example: "/home/images".
            match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 
            注意这个正则表达式只会应用到 base filename 而不是
            路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
            recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
            这三个参数可以同时使用.
            match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
            FilePathField(path="/home/images", match="foo.*", recursive=True)
            ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif
     
    <15> IPAddressField
            一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
    <16> CommaSeparatedIntegerField
            用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
     
    

    更多参数

    1)null
     
    如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
     
    (1)blank
     
    如果为True,该字段允许不填。默认为False。
    要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
    如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
     
    (2)default
     
    字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
     
    (3)primary_key
     
    如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
    Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
    否则没必要设置任何一个字段的primary_key=True。
     
    (4)unique
     
    如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
     
    (5)choices
    由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
    (6)db_index
      如果db_index=True 则代表着为此字段设置数据库索引。
    
    
    DatetimeField、DateField、TimeField这个三个时间字段,都可以设置如下属性。
    
    (7)auto_now_add
        配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
    
    (8)auto_now
        配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。
    

    单表增加记录

    2步曲

    第1步引入对应的models.py文件
    第2步 书写添加数据语句 有2种方式
    

    实列

    第1种添加方式
    from app01 import models
    def tj(request):
        new_obj = models.UserInfo(
            id=1,
            name='小白',
            bday='2019-09-27',  # current_date
            checked=1,
        )
        new_obj.save()  # 翻译成sql语句,然后调用pymysql,发送给服务端
        print(new_obj)#UserInfo object 对象
        print(new_obj.name)
        return HttpResponse('tj成功')
    
    
    第2种添加方式
    from app01 import models
    def tj(request):
        ret = models.UserInfo.objects.create(
            name='小白1',
            bday='2019-09-27',
            checked=0
        )
        print(ret)#UserInfo object 对象
        print(ret.name)
        return HttpResponse('tj成功')
    
       
    
    
    增加时间出现的bug
    import datetime
    current_date = datetime.datetime.now()
    
    models.UserInfo.objects.create(
            name='杨泽涛2',
            bday='2019-09-27',# 直接插入时间没有时区问题
        	cszhiduan=current_date,# 系统插入时间有时区问题current_date是当前时间
            checked=0
        )
    	但是如果让这个字段自动来插入时间,就会有时区的问题, auto_now_add可以使创建记录时自动添加当前创建记录时的时间,存在时区问题
    cszhiduan = models.DateTimeField(auto_now_add=True,null=True)
    
    解决方法:
        settings配置文件中将USE_TZ的值改为False
        # USE_TZ = True
        USE_TZ = False  # 告诉mysql存储时间时按照当地时间来寸,不要用utc时间
    使用pycharm的数据库客户端的时候,时区问题要注意
    
    
    批量插入数据
        # bulk_create
        obj_list = []
        for i in range(20):
            obj = models.Book(
                title=f'金xx{i}',
                price=20+i,
                publish_date=f'2019-09-{i+1}',
                publish='24期出版社'
            )
            obj_list.append(obj)
    
        models.Book.objects.bulk_create(obj_list)  #批量创建
        
        
    request.POST --  querydict类型 {'title': ['asdf '], 'price': ['212'], 'publish_date': ['2019-09-12'], 'publish': ['asdf ']}
    data = request.POST.dict() -- 能够将querydict转换为普通的python字典格式
    
    创建数据
    	models.Book.objects.create(
                # title=title,
                # price=price,
                # publish_date=publish_date,
                # publish=publish
                **data
            )
    
    

    查询表纪录

    在学查表前先搞清楚
    queryset是查询集是什么?model对象是什么?
    	queryset是类似列表 里面是model对象 queryset的方法model对象不一定可以用
    	model对象可以用点取值 而queryset不可以
    
    
    
    13个查询api
    model对象可以点出来 queryset对象相互转换  只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的
    
    <1> all():                  查询所有结果,结果是queryset类型
      查询所有的数据  .all方法 返回的是queryset集合
        all_objs = models.Student.objects.all()  # 类似于列表  --  queryset集合
        for i in all_objs:
             print(i.name)
        print(all_objs)
        
        
        
    <2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 Book.objects.filter(title='linux',price=100) #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,
      	models.Student.objects.all().filter(id=7)  queryset类型可以调用fitler在过滤
      
    
    <3> get(**kwargs):          返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,
                                如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。  Book.objects.get(id=1)
      
    <4> exclude(**kwargs):      排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 Book.objects.exclude(id=6),返回id不等于6的所有的对象,或者在queryset基础上调用,Book.objects.all().exclude(id=6)
        exclude(**kwargs): 排除,objects控制器和queryset集合都可以调用,返回结果是queryset类型
        query = models.Student.objects.exclude(id=1)
        print(query)
        query = models.Student.objects.filter(age=38).exclude(id=6)
        print(query)
                     
    <5> order_by(*field): 排序      queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型
                      models.Book.objects.all().order_by('price','id') #直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-cs'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
            
            
    <6> reverse():              queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型
    			# 只可以排序之后反转
      		    # query = models.Student.objects.all().order_by('id').reverse()
        		# print(query)
    
    <7> count():       queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。
      
    <8> first():    queryset类型的数据来调用 ,返回第一条记录结果为model对象类型 Book值    
      
    <9> last():                queryset类型的数据来调用,返回最后一条记录,结果为model对象类型
      
    <10> exists():              queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False
                       空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits
                     例:all_books = models.Book.objects.all().exists() #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
    
    <11> values(*field):        用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                                model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。 里面可以加子段显示
            
    <12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 里面可以加子段显示
     
    <13> distinct():            values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录 去重,结果还是queryset 里面不可以传参 显示nanme等等可以用来去重
    	query = models.Student.objects.all().values('age').distinct()
        print(query)
    	
    
    
    基于双下划线的模糊查询
    Book.objects.filter(price__in=[100,200,300]) #price值等于这三个里面的任意一个的对象
    Book.objects.filter(price__gt=100)  #大于,大于等于是price__gte=100,别写price>100,这种参数不支持
    Book.objects.filter(price__lt=100) 小于
    Book.objects.filter(price__range=[100,200])  #sql的between and,大于等于100,小于等于200
    Book.objects.filter(title__contains="python")  #title值中包含python的
    Book.objects.filter(title__icontains="python") #不区分大小写
    Book.objects.filter(title__startswith="py") #以什么开头,istartswith  不区分大小写
    Book.objects.filter(pub_date__year=2012) date类型
    
    models.Book.objects.filter(publish_date__year='2019',publish_date__month='8',publish_date__day='1')
    
    models.Book.objects.filter(publish_date__isnull=True) #这个字段值为空的那些数据
    
    
    实列
    # all_books = models.Book.objects.filter(pub_date__year=2012) #找2012年的所有书籍
        # all_books = models.Book.objects.filter(pub_date__year__gt=2012)#找大于2012年的所有书籍
        all_books = models.Book.objects.filter(pub_date__year=2019,pub_date__month=2)#找2019年月份的所有书籍,如果明明有结果,你却查不出结果,是因为mysql数据库的时区和咱们django的时区不同导致的,了解一下就行了,你需要做的就是将django中的settings配置文件里面的USE_TZ = True改为False,就可以查到结果了,以后这个值就改为False,而且就是因为咱们用的mysql数据库才会有这个问题,其他数据库没有这个问题。
    
    

    删除表纪录

    简单查询:filter()  -- 结果是queryset类型的数据里面是一个个的model对象,类似于列表
    	models.UserInfo.objects.filter(id=7).delete()  #queryset对象调用
    	models.UserInfo.objects.filter(id=7)[0].delete()  #model对象调用
    
    

    修改表纪录

    方式1:update
         models.UserInfo.objects.filter(id=2).update(
             name='篮子文',
             checked = 0,
        
         )
         #错误示例,model对象不能调用update方法
         models.UserInfo.objects.filter(id=2)[0].update(
             name='加篮子+2',
             # checked = 0,
         )
    方式2 
        ret = models.UserInfo.objects.filter(id=2)[0]
        ret.name = '加篮子+2'
        ret.checked = 1
        ret.save()
        
    
    更新时的auto_now参数
    	# 更新记录时,自动更新时间,创建新纪录时也会帮你自动添加创建时的时间,但是在更新时只有使用save方法的方式2的形式更新才能自动更新时间,有缺陷,放弃
        now2 = models.DateTimeField(auto_now=True,null=True)
    
    

    为什么要在类模型定义__str__方法?

    为了便于观察 打印一个对象,让他显示一个能够看懂的值,__str__,当print()打印实例化对象时会调用__str__()
    
    from django.db import models
    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,)
        pub_date = models.DateTimeField() #必须存这种格式"2012-12-12"
        publish = models.CharField(max_length=32)
        def __str__(self): #后添加这个str方法,也不需要重新执行同步数据库的指令
            return self.title #当我们打印这个类的对象的时候,显示title值
    
    

    小练习 基于单表 增删改查

    图书管理系统
    实现对书籍的查看 新增 删除
    内容和样式如下:
    查看页面
    
    

    解题思路

    查看功能的实现
    创建一张表 里面有 id 名称 价格 日期 出版社 字段
    html
    写页面记得 配置静态文件 利用orm .all获得查询集和 传给前端 前端 for 模板渲染
        STATIC_URL = '/static/'  #静态文件路径别名
    
        STATICFILES_DIRS = [
            os.path.join(BASE_DIR, '项目下创建的文件夹名'),第2个参数创建的文件夹名
        ]
    <link rel="stylesheet" href="/别名/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    
    def showbooks(request):
        if request.method == 'GET':
            books=models.Boo.objects.all()
            print(books)
            return render(request,'showbooks.html',{'books':books})
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    </head>
    <body>
    
    <h1>查看书籍</h1>
    
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                    <a href="/add_book/" class="btn btn-primary">添加书籍</a>
                    <table class="table table-striped table-hover">
                    <thead>
                    <tr>
                        <th>编号</th>
                        <th>书籍名称</th>
                        <th>价格</th>
                        <th>出版日期</th>
                        <th>出版社</th>
                        <th>操作</th>
                    </tr>
                    </thead>
                    <tbody>
                    {% for book in books %}
    
                        <tr>
                            <td>{{ forloop.counter }}</td>
                            <td>{{ book.title }}</td>
                            <td>{{ book.price }}</td>
                            <td>{{ book.c_date|date:'Y-m-d' }}</td>
                            <td>{{ book.press }}</td>
                            <td>
                                <a href="" class="btn btn-warning">编辑</a>
                                <a href="" class="btn btn-danger">删除</a>
                            </td>
                        </tr>
    
                    {% endfor %}
    
                    </tbody>
    
                </table>
    
    
            </div>
    
        </div>
    
    </div>
    
    </body>
    </html>
    
    
    
    添加功能的实现
    点击a标签 跳转页面(注意不用别名 要加/)
    <a href="/add_book/" class="btn btn-primary">添加书籍</a>
    input标签name值最好设置与表字段相同
    返回查看页面 要用重定向 不然不走url分发 orm取不到数据库数据
     return render(request,'showbooks.html')
    
    def add_book(request):
        if request.method == 'GET':
            return render(request,'add_book.html')
        else:
            ret = request.POST.dict()
            ret.pop('csrfmiddlewaretoken')
            print()
            models.Boo.objects.create(
                **(ret)
            )
            return render(request,'showbooks.html')
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    </head>
    <body>
    
    <h1>添加书籍</h1>
    
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <form action="" method="post">
                    {% csrf_token %}
                  <div class="form-group">
                    <label for="title">书籍名称</label>{# "for" 属性的值设置为相关元素的 id 属性的值。#}
                    <input type="text" class="form-control" id="title" placeholder="title" name="name">
                  </div>
                  <div class="form-group">
                    <label for="price">价格</label>
                    <input type="number" class="form-control" id="price" placeholder="price" name="price">
                  </div>
                   <div class="form-group">
                    <label for="publish_date">出版日期</label>
                    <input type="date" class="form-control" id="publish_date" placeholder="publish_date" name="c_date">
                  </div>
                   <div class="form-group">
                    <label for="publish">出版社</label>
                    <input type="text" class="form-control" id="publish" placeholder="publish" name="press">
                  </div>
    
                  <button type="submit" class="btn btn-success pull-right">提交</button>
                </form>
    
    
            </div>
    
        </div>
    
    
    
    </div>
    
    
    </body>
    </html>
    
    

    删除功能的实现

    <a href="{% url 'delete_book' book.pk %}" class="btn btn-danger">删除</a>
    对象.pk 就是独一无2的
    models.Book.objects.filter(id=n).delete()
    
    

    编辑功能的实现

    点击编辑按钮pk传过去  获取到对象 对象传过去
    修改values值 注意时间  {{ book_obj.publish_date|date:'Y-m-d' }}
    
    <a href="{% url 'edit_book' book.pk %}" class="btn btn-warning">编辑</a>
    
    
    def edit_book(request,n):
        book_obj = models.Book.objects.filter(pk=n)
        if request.method == 'GET':
    
            return render(request,'edit_book.html',{'book_obj':book_obj.first()})
        else:
            print(request.POST)
            # <QueryDict: {'title': ['金xx7777'], 'price': ['27.00'], 'publish_date': ['2019-09-08'], 'publish': ['24期出版社xx']}>
            ret = request.POST.dict()
    
            book_obj.update(
                **ret
            )
    
            return redirect('showbooks')
    
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    </head>
    <body>
    
    <h1>编辑书籍</h1>
    
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
    
                <form action="" method="post">
                  <div class="form-group">
                    <label for="title">书籍名称</label>
                    <input type="text" class="form-control" id="title" placeholder="title" name="title" value="{{ book_obj.title }}">
                  </div>
                  <div class="form-group">
                    <label for="price">价格</label>
                    <input type="number" class="form-control" id="price" placeholder="price" name="price" value="{{ book_obj.price }}">
                  </div>
                   <div class="form-group">
                    <label for="publish_date">出版日期</label>
                    <input type="date" class="form-control" id="publish_date" placeholder="publish_date" name="publish_date" value="{{ book_obj.publish_date|date:'Y-m-d' }}">
                  </div>
                   <div class="form-group">
                    <label for="publish">出版社</label>
                    <input type="text" class="form-control" id="publish" placeholder="publish" name="publish" value="{{ book_obj.publish }}">
                  </div>
    
                  <button type="submit" class="btn btn-success pull-right">提交</button>
                </form>
    
            </div>
    
        </div>
    
    
    
    </div>
    
    
    
    
    
    
    </body>
    </html>
    
    
  • 相关阅读:
    119. Pascal's Triangle II
    118. Pascal's Triangle
    112. Path Sum
    111. Minimum Depth of Binary Tree
    110. Balanced Binary Tree
    108. Convert Sorted Array to Binary Search Tree
    88. Merge Sorted Array
    83. Remove Duplicates from Sorted List
    70. Climbing Stairs
    陌陌面试经历
  • 原文地址:https://www.cnblogs.com/saoqiang/p/12396903.html
Copyright © 2011-2022 走看看