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分)总数。

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

  • 相关阅读:
    [CodeForces]Codeforces Round #429 (Div. 2) ABC(待补)
    About Me
    2018-06-14
    Codeforces Codeforces Round #484 (Div. 2) E. Billiard
    Codeforces Codeforces Round #484 (Div. 2) D. Shark
    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings
    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes
    Codeforces Avito Code Challenge 2018 D. Bookshelves
    Codeforces Round #485 (Div. 2) D. Fair
    Codeforces Round #485 (Div. 2) F. AND Graph
  • 原文地址:https://www.cnblogs.com/qwj-sysu/p/4154021.html
Copyright © 2011-2022 走看看