• 多表查询, 聚集查询和分组查询


     

     

    有如下模型为例

    class Publisher(models.Model):
        name = models.CharField(max_length=30)
        address = models.CharField(max_length=50) 
        website = models.URLField()
    
    class Author(models.Model):
        name = models.CharField(max_length=30)
    
    class AuthorDetail(models.Model):
        sex = models.BooleanField(max_length=1, choices=((0,''),(1,''),))
        email = models.EmailField()
        birthday = models.DateField()
        author = models.OneToOneField(Author, on_delete=models.CASCADE)
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
        authors = models.ManyToManyField(Author)
        publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
        publication_date = models.DateField()

     

    一. 多表查询
     
    1)查询作者的所有完整信息
    注意authordetail表中没有作者名字,名字在author表中
    AuthorDetail.objects.values('sex','email','address','author__name')
    author是AuthorDetail表中的外键字段,在外键后面加2个下划线跟上Author表中的name属性,就可输出Author表中的名字
     
    如果想单独获得某个作者的姓名,如下
    author_detail = AuthorDetail.objects.filter(email="123@qq.com")
    name1 = author_detail.author.name
     
     
     
    2)查询<<我的祖国>>这本书的作者名字,出版社名字
    书和作者是多对多关系
    Book.objects.filter(title='我的祖国').values('authors__name')
    Book.objects.filter(title='我的祖国').values('publisher__name')
     
    3)查询胡大海写了什么书
    Book.objects.filter(authors__name='胡大海').values('title')
     
    4)查询广东人民出版社出了什么书
    Book.objects.filter(publisher__name='广东人民出版社').values('title')
     
    5)查询广东人民出版社都有哪些作者出过书
    Book.objects.filter(publisher__name='广东人民出版社').values('author__name')
     
     
    多表查询技巧
    1. 两个下划线可生成连接查询,查询关联的字段信息,可用于外键查询主键字段信息,用objects操作
    例如:book = Book.objects.filter(publisher__name='广东人民出版社')
     
    2. _set提供了对象访问相关联表数据的方法,使用外键相关模型的小写名称,下划线和单词set。但是这种方法只能是关键类访问外键类
    我们有模型Publisher和Book,而Book类中我们通过外键关联到了Publisher。
    下面我们定义一个publisher对象表示一个出版社,就可以使用publisher.book_set的方法获取相关联的书籍信息了
    publisher = Publisher.objects.get(name='广东人民出版社')
    publisher.book_set.all().values()
     
    book.authors_set.all() 这种方法会报错
    因为authors不是Book类中的外键,这样操作行不通
     
     
    注意:
    使用filter过滤的时候,不仅仅可以指定本模型上的某个属性要满足什么条件,还可以指定相关联的模型满足什么属性
    比如查找所有书的标题为title1的出版商
    pubs = Publisher.objects.filter(book__title = "title1")    #注意这里用Book类的小写加__title的方式
     
     
     
     
    二. 常见的查询方法
    常见的查询相关的API
    1)get(**kwargs):返回于所有筛选条件相匹配的对象,返回结果只有一个。如果符合条件的对象超过一个,就抛出MultipleObjectsReturn异常,如果没找到符合条件的对象,抛出DoesNotExist异常。
    注意:
    它返回的不是QuerySet对象,而是models的对象,比如pub=Publisher.object.get(id=1)
    type(pub)返回结果为class 'hello.models.Publisher'
     
    2)all(): 查询所有结果
    3)filter(**kwargs):包含与所筛选条件相匹配的对象,结果可有多个
    4)exclude(**kwargs):包含那些与所选条件不匹配的对象,和filter相反
    5)order_by(*fields):对查询结果排序
    6)reverse():对查询结果反向排序
    7)distinct():从返回结果中剔除重复记录
    8)values(*fields):返回一个ValuesQuerySet, 一个特殊的QuerySet子类,运行后得到的是一个可迭代的字典序列
    9)values_list(*fields): 与values()功能一样,只是返回结果是元组序列
    10)count():返回数据库中匹配查询(QuerySet)的对象数量
    11)first(): 返回第一条记录,等价于[:1][0]
    例如Publisher.objects.all().first()
    12) last(): 返回最后一个记录,等价于[::-1][0]
    13) exists() :如果QuerySet包含数据,就返回True,否则返回False
    例如:Publisher.objects.all().exists()
     
     

     

    三.  聚集查询和分组查询 

    先看QuerySet里的两个函数 
    1. annotate(*args,**kwargs):可以为QuerySet中的每个对象添加注解。通过计算查询结果中的每个对象所关联的对象集合,得到总值(也可以是平均值等),用于分组查询
    2. aggregate(*args, **kwargs): 通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中的每个参数指定一个包含在字典中的返回值。用于聚合查询

     一些聚合函数所在位置:django.db.models,举例如下

    1. Avg: 返回所给字段平均值
    2. Count:根据所给的关联字段返回被关联model的数量
    3. Max: 返回所给字段的最大值
    4. Min:返回所给字段的最小值
    5. Sum:计算所给字段值总和
     
    实例 
    1. 在Book模型中增加一个price属性
    price = models.DecimalField(max_digits=5, decimal_places=2, default=10)
     
    2. 查询广东人民出版社出了多少本书 
    Publisher.objects.filter(name='广东人民出版社').count() #注意count是小写, 是QuerySet提供的一个方法
    如果使用聚合函数,如下
    from django.db.models import *
    Publisher.objects.filter(name='广东人民出版社').aggregate(Count('name'))
     
    可以自定义个别名 
    Publisher.objects.filter(name='广东人民出版社').aggregate(mycount = Count('name'))
     
    3. 查询胡大海出的书的总价格是多少
    Book.objects.filter(authors__name = '胡大海').aggregate(Sum('price'))
     
    4. 查询各作者出书的总价格是多少, 需要进行分组
    Book.objects.values('authors__name').annotate(Sum('price'))
    其中values()可以当做分组条件,annotate()用于分组查询
     
    5. 查询各出版社最便宜的书价 
    Book.objects.values('publisher__name').annotate(Min('price'))
    on_delete=models.CASCADE
  • 相关阅读:
    Fiddler的使用
    vue后台管理系统搭建
    有效的山脉数组
    从中序与后序遍历序列构造二叉树
    从前序与中序遍历序列构造二叉树
    最大二叉树
    填充每个节点的下一个右侧节点指针
    二叉树展开为链表
    翻转二叉树
    Java判断字符串是否为数字
  • 原文地址:https://www.cnblogs.com/regit/p/9243452.html
Copyright © 2020-2023  润新知