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对象中包含多个字典

猜你喜欢

转载自www.cnblogs.com/gyk1030/p/10804037.html