zoukankan      html  css  js  c++  java
  • Django-orm:单表查询、基于对象和双下划线的多表操作、集合查询、分组查询、F查询和Q查询

    ############################################## 单表操作 ##############################################
    简单查:
        models.User.objects.filter(id=3)               # queryset对象,相当于一个列表,放了一个或多个User对象
        models.User.objects.filter(id=3).first()    # User对象,相当于只去了queryset对象中的第一个
    
    增:
        第一种:# 先创建数据,再保存
            user = models.User(username='alex',password='a654321')
            user.save()
        第二种:# 直接保存或先创建再保存
            1.方式一:
            models.User.objects.create(username='alex',password='a654321')
            2.方式二:
            dic={"username":"alex","password":'a654321'}
            models.Book.object.create(**dic)
    
    删:
        方式一:# 删除所查出queryset对象中所有对象
            models.User.objects.filter(id=3).delete()
        方式二:# 删除所查出的user对象
            user = models.User.objects.filter(id=3).first()
            user.delete()
    
    改:
        方式一:# 将修改所查到queryset对象中所有的对象
            models.User.objects.filter(id=3).update(username='egon',password='aa123')
        方式二:# 只修改所查到的user对象,一般在收集日志的时候用此方法,因为有save()动作
            user = models.User.objects.filter(id=3).first()
            user.username='egon'
            user.password='aa123'
            user.save()
            
    查:
        查询相关API:
            <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
            <2>all():                 查询所有结果
            <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
            #---------下面的方法都是对查询的结果再进行处理:比如 objects.filter().values()--------
            '''
                **kwargs:代表以键值(字段=值)的方法传参
                *field:代表只传键(字段),不传值
            '''
            <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
            <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象  # 可直接用,也可用在filter之后
            <6>order_by(*field):      对查询结果排序              # 只能用在queryset之后
            <7>reverse():             对查询结果反向排序          # 必须用在order_by之后
            <8>distinct():            从返回结果中剔除重复纪录  # 一般用在values之后,对某一字段进行去重
            <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列  # 将values()字典中的值拿了出来,组成元组
            <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。  # 只能用在queryset对象之后
            <11>first():              返回第一条记录
            <12>last():               返回最后一条记录
            <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。  # 只能用在queryset之后
        
        基于双下划线__的模糊查询:
            models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
            models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
            models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
            models.Tb1.objects.filter(id__range=[1, 2])      # 范围bettwen and
            models.Tb1.objects.filter(name__contains="ven")  # name中包含ven的,对大小写敏感
            models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
            ....startswith(以什么开头)
            ....istartswith(返回Bool值)
            ....endswith(以什么结尾)
            ....iendswith(返回Bool值)
            
    
            
    # ****************小Tip***************
        1.user = models.User.objects.filter(id=3)
          print(user.query)  # 打印其原生SQL
        2.pk即id,pk指主键,一般id也作为主键
        3.models中,在创建一对一和一对多关系时,需要添加约束:"on_delete=models.CASCADE",意为在删除被关联字段时,必须删除其关联的所有字段,称为“级联删除”
        4.正向查询:关联字段在当前表中,从当前表向外查
          反向查询:关联字段不在当前表中,从当前表向外查
    # ************************************
    
    
    ############################################## 多表操作 ##############################################
    多表操作相对于单表来说只是多了约束条件,只要在操作时考虑到相关联的表就行了
    
    例:'''
        author表:name
        detail表:age,sex,addr
        book表:name,pub_date
        publisher表:name,addr
        
        author和detail之间存在一对一关系,其关联字段'det_auth'写在detail中
        book和publisher之间存在一对多关系,其关联字段'book_pub'写在book中
        book和author之间存在多对多关系,其关联字段'book_auth'写在book中
        '''
        
    增:
        # ********顺序为先创建被关联方,再创建关联方********
        一对一(OneToOne):
            models.Author.objects.create(name='alex')
            models.Detail.objects.create(age=38,sex='male',det_auth_id=1)  # 其中det_auth_id为关联字段,必须得写,_id是django自己加上去的(也可换成pk)
            或
            author = models.Author.objects.create(name='alex')
            models.Detail.objects.create(age=38,sex='male',det_auth=author)  # 传对象方式
        一对多(ForeignKey):#与一对一相似
        多对多(ManyToMany):
            book = models.Book.objects.filter(id=3).first()
            book.book_auth.add(1,2)  # 在给id为3的书添加了id为1和2的两个作者
            或
            book = models.Book.objects.filter(id=3).first()
            author1 = models.Author.objects.get(id=1)
            author2 = models.Author.objects.get(id=2)
            book.book_auth.add(author1,author2)  # 传对象方式
    
    删:
        一对一and一对多:
            # ********删除被关联方字段,其所有的关联方字段都会被删除********
            models.Author.objests.filter(id=3).delete()
            models.Publisher.objests.filter(id=3).delete()
        多对多:
            book = models.Book.objects.filter(id=3)
            方式一:
                book.book_auth.clear()  # 将book下关联的所有都删掉
            方式二:
                book.book_auth.remove(1,2)  # 传id方式
                或
                author1 = models.Author.objects.get(id=1)
                author2 = models.Author.objects.get(id=2)
                book.book_auth.remove(author1,author2)  # 传对象方式
        
    改:
        一对一and一对多:
            models.Detail.objects.update(det_auth_id=3)
            或 
            author = models.Author.objects.get(id=3)
            models.Detail.objects.update(det_auth=author)  # 传对象方式
        多对多:
            book = models.Book.objects.filter(id=3)
            方式一:
                全部clear,再add
            方式二:
                book.book_auth.set([3,])  # 传id方式
                或 
                author1 = models.Author.objects.get(id=1)
                author2 = models.Author.objects.get(id=2)
                book.book_auth.set(author1,author2)  # 传对象方式
        
    查:
        # ******************基于对象的跨表查询(子查询)*********************
        '''
            总结:
                已知谁以谁为基表进行查询
                一对一:正向查询按关联字段,反向查询按表名小写
                一对多:正向查询按关联字段,反向查询按表名小写_set.all()(因为可能查到多条数据)
                多对多:正向查询按关联字段.all(),反向查询按表名小写_set.all()(因为可能查到多条数据)
        '''
        一对一:
            例1:查询地址为北京的人的名字
                detial = models.Detail.objects.filter(addr='北京').first()
                print(detail.det_auth.name)  # 正向查
            例2:查询alex这个人的地址
                author = models.Author.objects.filter(name='alex').first()
                print(author.detail.addr)  # 反向查
        一对多:
            例1:查询红楼梦这本书的出版社地址
                book = models.Book.objects.filter(name='红楼梦').first()
                print(book.book_pub.addr)  # 正向查
            例2:查询南京出版社出版的所有书的名字
                publisher = models.Publisher.objects.filter(name='南京出版社').first()
                books = publisher.book_set.all()  # 反向查,查到的是个queryset对象(可迭代)
                for book in books:
                    print(book.name)
        多对多:
            例1:查询红楼梦这本书的所有作者
                book = models.Book.objects.filter(name='红楼梦').first()
                authors = book.book_auth.all()  # 正向查,查到的是个queryset对象(可迭代)
                for author in authors:
                    print(author.name)
            例2:查询作者为alex写的所有书
                author = models.Author.objects.filter(name='alex').first()
                books = author.book_set.all()  # 反向查,查到的是个queryset对象(可迭代)
                for book in books:
                    print(book.name)
            
        # ******************基于双下划线__的跨表查询(子查询)*********************
        '''
            总结:
                1.基表可以是已知方,也可以是未知方,但必须相关
                2.基本上已经不区分一对一、一对多、多对多
            3.本质就是用了sql中的join连表查
                3.相比于基于对象查询:没有_set.all(),也不用关联字段.all()
                    优势:1.写起来比较方便,需要记得东西少
                 2.跨多表查询起来很方便
                    劣势:查询速度较慢,查询出来的是值,而不是对象,所以不能用.的方式进行连表查
        '''
        一对一:
            例1:查询alex这个人的地址
                -以Author表作为基表:
                    ret = models.Author.objects.filter(name='alex').values('name','detail__addr')  # 反向查
                    print(ret)
                -以Detail表作为基表:
                    ret = models.Detail.objects.filter(det_auth__name='alex').values('det_auth__name','addr')  # 正向查
                    print(ret)
            例2:查询地址为武汉的人的名字
                -以Author表作为基表:
                    ret = models.Author.objects.filter(detail__addr='武汉').values('name','detail__addr')  # 反向查
                    print(ret)
                -以Detail表作为基表:
                    ret = models.Detail.objects.filter(addr='武汉').values('det_auth__name','addr')  # 正向查
                    print(ret)
        一对多:
            例1:查红楼梦这本书的出版社地址
                -以Book作为基表:
                    ret = models.Book.objects.filter(name='红楼梦').values('name','book_pub__addr')  # 正向查
                    print(ret)
                -以Publisher作为基表:
                    rets = models.Publisher.objects.filter(book__name='红楼梦').values('book__name','addr')  # 反向查
                    print(ret)
            例2:查询南京出版社出版的所有书的名字
                -以Book作为基表:
                    rets = models.Book.objects.filter(book_pub__name='南京出版社').values('name')  # 正向查
                    for ret in rets:
                        print(ret)
                -以Publisher作为基表:
                    rets = models.Publisher.objects.filter(name='南京出版社').values('book__name')  # 反向查 
                    for ret in rets:
                        print(ret)
        多对多:
            例1:查询红楼梦这本书的所有作者
                -以Book作为基表:
                    rets = models.Book.objects.filter(name='红楼梦').values('name','book_auth__name')  # 正向查
                    for ret in rets:
                        print(ret)
                -以Author作为基表:
                    rets = models.Author.objects.filter(book__name='红楼梦').values('book__name','name')  # 反向查
                    for ret in rets:
                        print(ret)
            例2:查询作者为alex写的所有书
                -以Book作为基表:
                    rets = models.Book.objects.filter(book_auth__name='alex').values('name')  # 正向查
                    for ret in rets:
                        print(ret)
                -以Author作为基表:
                    rets = models.Author.objects.filter(name='alex').values('book__name')  # 反向查
                    for ret in rets:
                        print(ret)
        终极练习(连跨多表查询):
            例:查询人民出版社出版过的所有书籍的名字及作者的姓名
                -以出版社作为基表
                    rets = models.Publisher.objects.filter(name='人民出版社').values('book__name','book__book_auth__name')
                -以书作为基表
                    rets = models.Book.objects.filter(book_pub='人民出版社').values('name','book_auth__name')
                    print(rets)  # 打印出来是一个queryset对象中包含多个字典
    
    ################################## 聚合查询 #######################################
    aggregate() # 返回结果是一个字典,键为django自动生成"字段名_函数名",值为所查询并计算的结果
    
    from django.db.models import Count,Avg,Max,Min,Sum
    ret = models.Book.objects.aggregate(Avg('price'))
    ret = models.Book.objects.aggregate(Max('price'))
    ret = models.Book.objects.aggregate(Min('price'),Count('price'),Sum('price'))
    print(ret)
    
    >>:{'price__min':'25.5','price__count':'35.8','price__sum':'40.3'}
    
    ################################## 分组查询 #######################################
    annotate() # 返回的值是queryset对象,在annotate中算出的结果可赋给一个新值,可以作为后续查询的条件,也可作为结果
    '''
      values在前,表示group by,在后,表示取值 
      filter在前,表示过滤(where),在后,表示having(对分组之后的结果再进行过滤)
    '''
    
    from django.db.models import Count,Avg,Max,Min,Sum
    
    例1:统计每一本书的作者个数
      book_list = models.Book.objects.all().annotate(author_num=Count(authors)).value('name','author_num')
      print(book_list)
    例2:统计每一个出版社的最便宜的书
      publishList=Publish.objects.annotate(MinPrice=Min("book__price"))
      for publish_obj in publishList:
        print(publish_obj.name,publish_obj.MinPrice)
    例3:统计不止一个作者的图书:(作者数量大于1)
      ret=models.Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num')
    例4:根据一本图书作者数量的多少对查询集 QuerySet进行排序
      ret = Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
    例5:查询各个作者出的书的总价格
      ret = models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price")
    例6:查询每个出版社的名称和书籍个数
      ret = models.Publish.objects.all().annotate(c=Count('book__name')).values('name','c')
    
    #################################F 查询和Q查询 #####################################
    from django.db.models import F,Q
    
    F:取出表中字段对应的值
    例1:查询评论数大于阅读数的书
      ret = models.Book.objects.filter(commit_num__gt=F('read_num'))
    
    例2:把所有书的评论数+1
      ret = models.Book.objects.all().update(commit_num=F('commit_num')+1)
    
    Q:查询,构造出与"&"、或"|"、非"~"的关系
      与:
      例:查询出书名为红楼梦并且价格为20的书
        ret = models.Book.objects.all().filter(Q(name='红楼梦')&Q(price=20))
      或:
      例:查询出书名为红楼梦或价格为20的书
        ret = models.Book.objects.all().filter(Q(name='红楼梦')|Q(price=20))
      非:
      例:查询出书名为不为红楼梦的书
        ret = models.Book.objects.all().filter(~Q(name='红楼梦'))
  • 相关阅读:
    MYSQL limit用法
    mybaties mapping中if
    执行数据库同时又调接口
    WITH (NOLOCK)
    SpringMVC转发和重定向区别!
    MyBatis的foreach语句详解
    SSM mapper.xml
    win7与virtualbox中centos文件共享
    PBOC2.0中消费交易流程
    PBOC2.0协议中电子存折/电子钱包中圈存交易流程
  • 原文地址:https://www.cnblogs.com/gyk1030/p/10804037.html
Copyright © 2011-2022 走看看