zoukankan      html  css  js  c++  java
  • 3:django models Making queries 高级进阶--聚合运算

    在前一遍文章django models Making queries里面我们提到了django常用的一些检索数据库的内容,

    下面我们来看一下更为高级的检索聚合运算

    这是我们要用到的模型

    class Author(models.Model):
       name = models.CharField(max_length=100)
       age = models.IntegerField()
       friends = models.ManyToManyField('self', blank=True)
    
    class Publisher(models.Model):
       name = models.CharField(max_length=300)
       num_awards = models.IntegerField()
    
    class Book(models.Model):
       isbn = models.CharField(max_length=9)
       name = models.CharField(max_length=300)
       pages = models.IntegerField()
       price = models.DecimalField(max_digits=10, decimal_places=2)
       rating = models.FloatField()
       authors = models.ManyToManyField(Author)
       publisher = models.ForeignKey(Publisher)
       pubdate = models.DateField()
    
    class Store(models.Model):
       name = models.CharField(max_length=300)
       books = models.ManyToManyField(Book)

    我们直接来看一些高级聚合运算的例子吧

    # Total number of books.
    >>> Book.objects.count()
    2452
    
    # Total number of books with publisher=BaloneyPress
    >>> Book.objects.filter(publisher__name='BaloneyPress').count()
    73
    
    # Average price across all books.
    >>> from django.db.models import Avg
    >>> Book.objects.all().aggregate(Avg('price'))
    {'price__avg': 34.35}
    
    # Max price across all books.
    >>> from django.db.models import Max
    >>> Book.objects.all().aggregate(Max('price'))
    {'price__max': Decimal('81.20')}
    
    # Each publisher, each with a count of books as a "num_books" attribute.
    >>> from django.db.models import Count
    >>> pubs = Publisher.objects.annotate(num_books=Count('book'))
    >>> pubs
    [<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]
    >>> pubs[0].num_books
    73
    
    # The top 5 publishers, in order by number of books.
    >>> from django.db.models import Count
    >>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
    >>> pubs[0].num_books
    1323

    aggregate(英文原意:a sum total of many heterogenous things taken together,中文释义:合计;集合体;总计)

    annotate(英文原意:add explanatory notes to or supply with critical comments,中文释义:注释;给…作注释或评注)

    结合上面给出的例子,我们似乎可以这样总结吧

    aggregate是对我们我们感兴趣的某一列进行一些操作,返回的是一个字典

    annotate是返回的是一个queryset,并且这个queryset有着我们需要的额外字段

    继续看一些annotate的例子吧

    # Build an annotated queryset
    >>> q = Book.objects.annotate(Count('authors'))
    # Interrogate the first object in the queryset
    >>> q[0]
    <Book: The Definitive Guide to Django>
    >>> q[0].authors__count
    2
    # Interrogate the second object in the queryset
    >>> q[1]
    <Book: Practical Django Projects>
    >>> q[1].authors__count
    1

    接下来我们来进行更高级的操作吧

    1:找出每间store的价格范围,很明显,如果你想要范围的结果包含store,你应该用annotate

    >>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price'))

    如果你只是想得出所有store的价格范围,你应该用aggregate

     Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price'))

    分组查询values()

    使用values()可以在查询前后给数据分组

    最后我们说几个关于查询顺序的例子

    1:annotate和values的顺序

    >>> Author.objects.values('name').annotate(average_rating=Avg('book__rating'))
    >>> Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rating')

    第一行的查询时先对作者分组(相同名字的作者的书会被归在一组),返回每个作者的平均排名

    第二行的查询会为每个作者生成一个average_rating,而且只会输出每个author的name和average_rating

    2:filter和annotate的顺序

    >>> Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0)
    >>> Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))

    两个查询都返回了至少出版了一本好书(评分大于3分)的出版商的列表。

    但是第一个查询的注解包含其该出版商发行的所有图书的总数;

    而第二个查询的注解只包含出版过好书的出版商的所发行的好书(评分大于3分)总数。

    在第一个查询中,注解在过滤器之前,所以过滤器对注解没有影响。在第二个查询中,过滤器在注解之前,所以,在计算注解值时,过滤器就限制了参与运算的对象的范围

  • 相关阅读:
    Make a web page as screensaver
    python写入sqlserver中文乱码问题
    单片机中的ROM,RAM和FLASH的作用
    单片机STM32F4系统内部中断和外部中断优先级问题
    单片机AHB和APB
    嵌入式编程中一些常用的转换函数
    'AVStream::codec': 被声明为已否
    Python安装Python_snappy安装失败
    .net core 数据库问题
    .net 5.0 中 CrystalQuartz 增加授权校验
  • 原文地址:https://www.cnblogs.com/qwj-sysu/p/4154021.html
Copyright © 2011-2022 走看看