• ORM增删改查


    #一、ORM单表的增删改查
    
        #表记录的添加
            from app1.models import *
            #方式1
            Author.objexts.create(name='alvin')
            #方式2
            Author.objects.create(**{'name':'alex'})
            
         #方式1
            author = Author(name='alvin')
            author.save()
            #方式2
            author = Author()
            author.name = 'alvin'
            author.save()
    
        #表记录的修改
            #方式1
                Book.object.filter(author='kang').update(price=100)
            #方式2(有save的效率低,不建议用)
                b = Book.objects.get(author='kang')
                b.price = 123
                b.save()
        #表记录的删除
            Book.objects.filter(author='kang').delete()
    
        #表记录的查找
    
            #相关查询API
            filter(**kwargs)   包含了与所给筛选条件相匹配的对象,按照条件选出结果
            all()   查询所有结果
            get(**kwargs)    返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会报错
    
            #下面的方法都是对查询的结果进行处理
            values(*field)    返回一个字典序列
            exclude(**kwargs)  包含了与所给筛选条件不匹配的对象,按照条件排除结果
            order_by(*field)   对查询结果进行排序
            reverse()   对查询结果反向排序
            distinct()   从返回结果中剔除重复记录
            values_list(*field)  返回的是一个元组序列,values返回的是一个字典序列
            count()   返回数据库中匹配查询(QuerySet)的对象数量
            first()  返回第一条记录
            last()  返回最后一条记录
            exists()   如果QuerySet包含数据,则返回True,否则返回False
    
            __gt大于
            __lt小于
            __in 等于
            __contains 按大写选择
            __icontains 不区分大小写
            __range  在什么之间
    
    # django 升级到2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常:
    # TypeError: init() missing 1 required positional argument: ‘on_delete’
    #
    # on_delete各个参数的含义如下:
    #
    #     on_delete=None,               # 删除关联表中的数据时,当前表与其关联的field的行为
    #     on_delete=models.CASCADE,     # 删除关联数据,与之关联也删除
    #     on_delete=models.DO_NOTHING,  # 删除关联数据,什么也不做
    #     on_delete=models.PROTECT,     # 删除关联数据,引发错误ProtectedError
    #     # models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True)
    #     on_delete=models.SET_NULL,    # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理)
    #     # models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值')
    #     on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理)
    #     on_delete=models.SET,         # 删除关联数据,
    #      a. 与之关联的值设置为指定值,设置:models.SET(值)
    #      b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
    #
    # 由于多对多(ManyToManyField)没有 on_delete 参数,所以以上只针对外键(ForeignKey)和一对一(OneToOneField)
    
    
    #二、ORM多表的增删改查
    
    # ORM多表1(一对多)
    
        # 添加
            Book.objects.create(name='python',price=34,pub_date='2021-01-01',publish_id=2)
            Book.objects.create(name='java',price=10,pub_date='2019-08-01',publish_id=3)
    
        # 修改
            Book.objects.filter(id=17).update(price=100,pub_date='1998-11-13')
    
        # 删除
            Book.objects.filter(name='php').delete()   #删除名字为PHP的书
    
        # 查询:
            # 实例1:查询人民出版社出过的所有书籍的名字和价格
                # 方式1
                pub_obj = Publish.objects.filter(name='人民出版社')[0]
                ret = Book.objects.filter(publish=pub_obj).values('name','price')
                print(ret)
    
                # 方式2
                pub_obj = Publish.objects.filter(name='人民出版社')[0]
                ret = pub_obj.book_set.all().values('name','price')
                print(ret)
    
                # 方式3(通过双下划线)
                ret = Book.objects.filter(publish__name='人民出版社').values('name','price')
                print(ret)
    
            # 实例2:查询python这本书出版社的名字
                # 方式1
                ret0 = Publish.objects.filter(book__name='python').values('name')
                print(ret0)
    
                # 方式2
                ret1 = Book.objects.filter(name='python').values('publish__name')
                print(ret1)
    
            # 实例3:通过对象来查找记录
                book_obj = Book.objects.get(name='python')
                print(book_obj)   #python
                print(book_obj.name)  #name=python
                print(book_obj.price)  #price=34
                print(book_obj.pub_date)   #pub_date=2021-01-01
                print(book_obj.publish)   #Publish object
                print(book_obj.publish.name)    #机械出版社
                print(book_obj.publish.city)  #上海
                print(book_obj.publish.id)  #2
                print(book_obj.publish_id)  #publish_id=2
                print(book_obj.id)    #id=13
    
            # 实例4:查询生产地在甘肃兰州的书的名字
                ret = Book.objects.filter(publish__city='甘肃兰州').values('name')
                print(ret)   #go和java
    
            # 实例5:查找生产时间在2010-01-01到2021-07-29之间出版的书
                ret = Book.objects.filter(pub_date__lt='2021-07-29',pub_date__gt='2010-01-01').values('name')  #__lt小于,__gt大于
                print(ret)  #python/linux/go/HTML/java
    
            # 实例6:查找java的出版社
                # 方式1
                ret = Publish.objects.filter(book__name='java').values('name')
                print(ret)    #甘肃出版社
    
                # 方式2
                ret = Book.objects.filter(name='java').values('publish__name')
                print(ret)
    
    # ORM多表2(多对多)
    
        #增加
            # 创建多对多的关系:author = models.ManyToManyField("Author")------>此时会自动生成关联表
            #(1)book_authors表添加信息
                #添加一条信息
                    book_obj = Book.objects.get(id=13)   #书的对象
                    author_objs = Author.objects.get(id=1)
                    book_obj.authors.add(author_objs)
                #添加多条信息
                    book_obj = Book.objects.get(id=19)
                    author_objs = Author.objects.all()
                    book_obj.authors.add(*author_objs)
    
            #(2)通过创建第三张表来添加信息
                Book_Author.objects.create(book_id=16,author_id=1)
    
        #修改
            修改与一对多修改方式一样
    
        #删除
            #对book_authors表删除信息(即删除自动生成表的信息)
                #删除一条信息
                    book_obj = Book.objects.get(id=19)
                    author_objs = Author.objects.get(id=1)
                    book_obj.authors.remove(author_objs)
                #删除多条信息
                    book_obj = Book.objects.get(id=19)
                    author_objs = Author.objects.all()
                    book_obj.authors.remove(*author_objs)
    
        #查询
            #(一)、通过对象的方式绑定关系(自动生成的第三张表的操作)
            #方式1
                book_obj = Book.objects.get(id=13)            
           print(book_obj.authors.all())  #QuerySet对象
           print(type(book_obj.authors.all()))  #<class 'django.db.models.query.QuerySet'>
    
            #方式2
                author_obj = Author.objects.get(id=2)            
           print(author_obj.book_set.all())        
    
        #(二)、通过创建的第三张表来查找
      
        #alex出过的书籍名称及价格
                ret = Book.objects.filter(book_author__author__name='alex').values('name','price')            
           print(ret)        
    
    #注:以下实例都使用自动生成的第三张表来操作
        #实例1:查找alex出过的书籍的名字及价格
                ret_0 = Book.objects.filter(authors__name='alex').values('name','price')            
           print(ret_0)  #<QuerySet [{'name': 'HTML', 'price': 540}, {'name': 'java', 'price': 10}, {'name': 'python', 'price': 34}]>
    
            #聚合函数:
                    annotate(*args,**kwargs):可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。
                    aggregate(*args,**kwargs):通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。
            #实例2:求price的平均值
                      ret_1 = Book.objects.all().aggregate(Avg('price'))                    
                 print(ret_1)                
    
            #实例3:求price的总和
                        ret_2 = Book.objects.all().aggregate(Sum('price'))                    
                print(ret_2)                
    
            #实例4:求price的最小值
                        ret_3 = Book.objects.all().aggregate(Min('price'))                    
                print(ret_3)  #{'price__min': 20}
    
                 #实例5:求price的最大值
                        ret_4 = Book.objects.all().aggregate(max_money=Max('price'))                    
                print(ret_4)   #{'max_money': 550}------>max_mongy是可以自己定义的
    
            #实例6:alex出过书的总价格
                       ret_5 = Book.objects.filter(authors__name='alex').aggregate(Sum('price'))                    
                print(ret_5)                
    
            #实例7:alex出过书的数量
                        ret_6 = Book.objects.filter(authors__name='alex').aggregate(Count('name'))                    
                print(ret_6)        
    
        #分组
            #实例8:求每个作者出过书的总价格
                    ret_7 = Book.objects.values('authors__name').annotate(Sum('price'))                
             print(ret_7)        
    
        #F查询:使用查询条件的值进行操作
            #实例9:为每本书增加10块钱
                    Book.objects.all().update(price=F('price')+10)        
    
        #Q查询:
            #实例10:找价格为44或者名字为go的
                    ret_8 = Book.objects.filter(Q(price=44) | Q(name='go'))                
              print(ret)            
    
            #实例11:查找书名中有P的书
                    ret_9 = Book.objects.filter(Q(name__contains='p'))                
             print(ret_9)            
      
            #实例12:查找书名中有l的并且价格为53的书
                    ret_10 = Book.objects.filter(Q(name__contains='l') & Q(price=53))                
             print(ret_10)   #linux
    
                #~(非)的使用
                    ret_11 = Book.objects.filter(Q(name__contains='l')& ~ Q(price=53))                
              print(ret_11)  #linux运维

    注:
    Djangoqueryset的惰性机制
    # <1>Djangoqueryset是惰性的
    #
    # Djangoqueryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
    # 到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
    # 上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
    # 这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。
    #
    # <2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
    # 为了验证这些,需要在settings里加入 LOGGING(验证方式)
    # obj=models.Book.objects.filter(id=3)
    # # for i in obj:
    # # print(i)
    #
    # # if obj:
    # # print("ok")
    #
    # <3>queryset是具有cache
    # 当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Djangomodel。这被称为执行
    # evaluation.这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset
    # 你不需要重复运行通用的查询。
    # obj=models.Book.objects.filter(id=3)
    #
    # # for i in obj:
    # # print(i)
    # ## models.Book.objects.filter(id=3).update(title="GO")
    # ## obj_new=models.Book.objects.filter(id=3)
    # # for i in obj:
    # # print(i) #LOGGING只会打印一次
    #
    # <4>
    # 简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
    # 数据!为了避免这个,可以用exists()方法来检查是否有数据:
    #
    # obj = Book.objects.filter(id=4)
    # # exists()的检查可以避免数据放入querysetcache
    # if obj.exists():
    # print("hello world!")
    #
    # <5>queryset非常巨大时,cache会成为问题
    #
    # 处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
    # 进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
    # 来获取数据,处理完数据就将其丢弃。
    # objs = Book.objects.all().iterator()
    # # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
    # for obj in objs:
    # print(obj.name)
    # #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
    # for obj in objs:
    # print(obj.name)
    #
    # #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
    # #iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询
    #
    # 总结:
    # querysetcache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
    # 使用exists()iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
    # 会造成额外的数据库查询。
     
  • 相关阅读:
    Java面试不得不知的程序(二)
    Java面试不得不知的问题(一)
    Java框架 面试题总结
    JavaSE 面试题总结
    JavaEE 面试题总结
    DBUtils 学习使用
    JavaWeb —— JSP 总结
    java 单例模式(singleton)
    java 上溯造型与下塑造型
    java 第六章 面向对象基础
  • 原文地址:https://www.cnblogs.com/shadowfolk/p/15085127.html
Copyright © 2020-2023  润新知