Django聚合查询、分组查询、F与Q查询

表查询

基于django settings源码实现自己的项目
配置文件的可插拔式设计
    dir()
    importlib
    反射

单表查询
    只要是queryset对象 就可以无限制的点击queryset对象的方法
    13条
        1.all()  # 查所有
        2.filter()  # 根据条件过滤 多个条件之间是and关系
        3.get()  # 直接获取数据对象  查询条件不存在直接报错
        4.first()  # 取queryset的第一个数据对象
        5.last()  # 取queryset的最后一个数据对象
        6.exclude()  # 除此之外 
        7.values()  # queryset 类似于列表套字典
        8.values_list()  # queryset 类似于列表套元组
        9.count()  # 统计数据个数
        10.distinct()  # 一定要是完全一样的数据才能去重
        11.order_by()  # 排序 默认是升序 加负号就变成降序
        12.reverse()  # 反转 排序之后才能反转
        13.exists()  # 判断queryset是否有值 结果是个布尔值
        
    神奇的双下线的查询
        price__gt
        price__lt
        price__gte
        price__lte
        price__in=[100,200,300]
        price__range=(200,800)
        title__contains  包含  模糊匹配
        title__icontains  忽略大小写
        publish_date__year  只针对年份
        publish_date__month  只针对月份
        title__startswith
        title__endswith 


多表查询
    前期表准备
        图书管理系统
            一对多
            多对多
            一对一
        
    外键字段的增删改查
        一对多字段
            create(publish_id=1)
            create(publish=publish_obj)
            
            update(publish_id=2)
            update(publish=publish_obj1)
            
            models.Publish.objects.filter(pk=2).delete()
            # orm外键默认是级联更新 级联删除的
        
        多对多字段
            # 朝第三张关系表中添加数据
            book_obj.authors.add(1)
            book_obj.authors.add(1,2,3,4)
            book_obj.authors.add(author_obj)
            book_obj.authors.add(author_obj,author_obj1,author_obj2)
            # 朝第三张表修改数据
            book_obj.authors.set((1,))
            book_obj.authors.set((1,2,3))
            book_obj.authors.set((author_obj,))
            book_obj.authors.set((author_obj,author_obj1))
            # 朝第三张表删除关系
            book_obj.authors.remove(1)
            book_obj.authors.remove(1,2,3,4)
            book_obj.authors.remove(author_obj)
            book_obj.authors.remove(author_obj,author_obj1)
            # 朝第三张表清空当前书籍对象所有的记录
            book_obj.authors.clear()
            
    跨表查询
        正反向的概念:
            外键字段在谁那儿 谁就是正向
            没有外键字段的  就是反向

        口诀:
            正向查询按字段
            反向查询按表名小写


        基于对象  # 子查询
            """
            步骤都是先获取一个数据对象
            然后利用对象点点点的方式查到锁对应的数据
            """
            # 正向
            book_obj.publish.name
            
            book_obj.authors.all()
            
            author_obj.author_detail.addr
            """
            外键字段所对应的数据 如果是单个 不需要加all
            如果是多个 需要加all()
            """
            # 反向
            publish_obj.book_set.all()
            
            author_obj.book_set.all()
            
            author_detail_obj.author.name
            """
            反向查询 数据如果是多个
            那么需要 表名小写_set.all()
            如果是一个  直接表名小写即可
            """ 
  
        基于双下划綫  # 连表查询
            """
            left join
            right join
            inner join
            union
            """
            # 正向
            models.Book.objects.filter(title='python').values('publish__name')
            # 写外键字段publish之后 就会跨到publish表中  你想要该表的哪个字段对应的数据  就加__字段名获取
            
            models.Book.objecst.filter(pk=1).values('authors__name')
            
            models.Author.objects.filter(name='jason').values('author_detail__addr')
            
            models.Publish.objects.filter(pk=1).values('book__title')
            models.authors.objects.filter(pk=1).values('book__title')
            models.AuthorDetail.objects.filter(pk=1).values('author__name')

            # 反向
            
            models.Publish.objects.filter(book__title='python').values('name')

            """查询书籍id为1 的作者的 手机号"""
            models.Book.objects.filter(pk=1).values('authors__author_detail__phone')



聚合查询
    聚合函数
        from django.db.models import Max,Min,Sum,Count,Avg
        
        


分组查询

F与Q查询

orm中常见字段
    AutoField(primary_key=True)
    CharField(max_length=32)   varchar(32)
    IntegerField()             int
    BigIntegerField()          long
    DateField()
        auto_now:每次修改数据的时候 都会更新该字段
        auto_now_add:只在创建数据的时候 才会自动将创建时间添加 后续不会再自动修改了
    DecimalField()
    BooleanField(Field)
        - 布尔值类型
        该字段在存储数据的时候 你只需要传布尔值即可
        对应到数据库中 会变成0/1
    TextField(Field)
        - 文本类型
        存大段文本
    EmailField(CharField)               varchar(...)
    FileField(Field)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

    DecimalField(Field)
    - 10进制小数
    - 参数:
        max_digits,小数总长度
        decimal_places,小数位长度


自定义char字段
    # 自定义char类型字段
    class MyCharField(models.Field):
        def __init__(self,max_length,*args,**kwargs):
            self.max_length = max_length
            super().__init__(max_length=max_length,*args,**kwargs)

        def db_type(self, connection):
            return 'char(%s)'%self.max_length

如果你使用的是django2.X版本 你在建数据库表关系的时候
你需要手动指定两个参数
    (你要手动告诉django  级联更新 级联删除  是否建外键约束)
    
    on_delete
    db_constraint

!!!!!!!!!!碎片化学习!!!!!!!


查询优化(面试比较喜欢问的)
    only与defer

    select_related和prefetch_related


django orm中的事务操作
    ACID
        原子性
        一致性
        隔离性
        持久性

        commit
        rollback
    要么同时成功要么同时失败
    
    from django.db import transaction
    with transaction.atomic():
        # 在该代码块中所写的orm语句 同属于一个事务
    # 缩进出来之后自动结束

聚合查询(aggregate)

from django.db.models import Max,Min,Count,Avg,Sum   #查询总和,平均,最大,最小

res = models.Book.objects.aggregate(Sum('price'))
res1 = models.Book.objects.aggregate(Avg('price'))
res2 = models.Book.objects.aggregate(Count('price'))
res3 = models.Book.objects.aggregate(Max('price'))
res4 = models.Book.objects.aggregate(Min('price'))
res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))  #也可以放在一个里面写

分组查询 (annotate)

 1.统计每一本书的作者个数

from django.db.models import Max, Min, Count, Avg, Sum

res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
 #book表根据authors分组求和,author_num是取的别名,values是控制台打印的值
2.统计每个出版社卖的最便宜的书的价格

res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
3.统计不止一个作者的图书

res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
4.查询每个作者出的书的总价格

res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')

F查询与Q查询

F查询的本质就是从数据库中获取某个字段的值,之前查询等号后面的条件都是我们人为输入的,现在变成了需要从数据库中获取数据放在等号后面

查询库存量大于卖出量的书籍

from django.db.models import F
res = models.Book.objects.filter(kucun__gt=F('maichu')) #kucun和maichu都是Book表的字段

将书籍库存数全部增加1000

models.Book.objects.update(kucun=F('kucun')+1000)

把所有书名后面加上'新款'

from django.db.models.functions import Concat
from django.db.models import Value

ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
models.Book.objects.update(title = F('title')+'新款')  # 不能这么写

Q查询 (filter里面条件都是与,Q支持与或非)

查询书籍名称是三国演义或者价格是444

from django.db.models import Q
res = models.Book.objects.filter(title='三国演义',price=444.44)  # filter只支持and关系
res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444))  # 如果用逗号 那么还是and关系
res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444))   #或者关系
res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444))  #查询除了title是三国演义,或者价格是444的书籍

Q的高级用法

from django.db.models import Q
q = Q()
q.connector = 'or'  # 修改查询条件的关系   默认是and
q.children.append(('title__contains','三国演义'))  # 往列表中添加筛选条件
q.children.append(('price__gt',444))  # 往列表中添加筛选条件
res = models.Book.objects.filter(q)  # filter支持你直接传q对象  但是默认还是and关系
print(res)

猜你喜欢

转载自www.cnblogs.com/chmily/p/11777985.html