首页 > 其他 > 详细

django-聚合、分组、F查询和Q查询、总结

时间:2020-06-12 21:43:37      阅读:42      评论:0      收藏:0      [点我收藏+]
django-聚合、分组、F查询和Q查询、总结
           
           
               
                   
                                       
                                       
                                       
                                       
                                       
                                                                                                                                            进击的小猿
                    2018-01-27 20:08:00
                   
                    14714
                   
                       
                       
                        收藏
                       
                                                8                                               
                   
                                       
               
               
               
                                           分类专栏:
                                                                                            
                                       PythonWeb框架                                  
                                                                                                                                  
               
               
                               
               
               
                                                                版权
                                   
           
       
   
   
                   
                
           
                           
                   
                   
                                           
 
准备测试数据
聚合查询
分组查询
F查询
Q查询
总结
 
 
 
 
准备测试数据
 
from django.db import models

# Create your models here.

class Publisher(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)
    phone = models.IntegerField
    def __str__(self):
        return self.name

# 作者查书,设计到作者里面
class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    author_detail = models.OneToOneField("AuthorDetail")
    # 多对多
    books = models.ManyToManyField(to="Book")
    def __str__(self):
        return self.name

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=6)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_day = models.DateField(auto_now_add=True)
    # 书-出版社 多对一关联
    publisher = models.ForeignKey(to="Publisher", to_field="id")
    def __str__(self):
        return self.title

class AuthorDetail(models.Model):
    id = models.AutoField(primary_key=True)
    city = models.CharField(max_length=32)
    email = models.EmailField()
    def __str__(self):
        return self.city1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
 
 
 
 
 

聚合查询
aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。
 
from django.db.models import Max,Avg,F,Q
models.Book.objects.all().aggregate(Avg("price"))
{‘price__avg‘: 192.593333}123
如果你想要为聚合值指定一个名称,可以向聚合子句提供它。
 
models.Book.objects.all().aggregate(avg_price=Avg("price"))
{‘avg_price‘: 192.593333}12
如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
 
from django.db.models import Max,Avg,F,Q,Min,Count,Sum
models.Book.objects.all().aggregate(Avg("price"),Max("price"),Min("price"),Sum("price"))
{‘price__avg‘: 192.593333, ‘price__max‘: Decimal(‘233.33‘), ‘price__min‘: Decimal(‘111.12‘), ‘price__sum‘: Decimal(‘577.78‘)}
1234
 
分组查询
为调用的QuerySet中每一个对象都生成一个独立的统计值
统计每一本书的作者个数
 
models.Book.objects.all().annotate(authorNum=Count("author"))
<QuerySet [<Book: 书一>, <Book: 书二>, <Book: 书三>]>
book_list = models.Book.objects.all().annotate(authorNum=Count("author"))
for i in book_list:
    print(i.authorNum)
2
2
112345678
统计出每个出版社买的最便宜的书的价格
方法一
 
pulisher_list = models.Publisher.objects.all().annotate(min_price=Min("book__price"))
for i in pulisher_list:
    print(i.min_price)
111.12
12.00
456.00
785.001234567
方法二
 
tmp = models.Book.objects.all().values("author__name").annotate(min_price=Min("price"))
for i in tmp:
    print(i.min_price)
Traceback (most recent call last):
  File "<input>", line 2, in <module>
AttributeError: ‘dict‘ object has no attribute ‘min_price‘
for i in tmp:
    print(i)
{‘author__name‘: ‘小一‘, ‘min_price‘: Decimal(‘111.12‘)}
{‘author__name‘: ‘小二‘, ‘min_price‘: Decimal(‘233.33‘)}
{‘author__name‘: ‘小三‘, ‘min_price‘: Decimal(‘111.12‘)}
{‘author__name‘: None, ‘min_price‘: Decimal(‘12.00‘)}12345678910111213
统计不止一个作者的图书
 
tmp = models.Book.objects.all().annotate(au=Count("author")).filter(au__gt=1)
tmp
<QuerySet [<Book: 书一>, <Book: 书二>]>123
根据一本图书作者数量的多少对查询集 QuerySet进行排序
 
tmp = models.Book.objects.all().annotate(au=Count("author")).order_by("au")
tmp
<QuerySet [<Book: 书四>, <Book: 书五>, <Book: 书六>, <Book: 书三>, <Book: 书一>, <Book: 书二>]>
1234
查询各个作者出的书的总价格
 
tmp = models.Author.objects.all().annotate(total=Sum("books__price")).values("name","total")
tmp
<QuerySet [{‘name‘: ‘小一‘, ‘total‘: Decimal(‘344.45‘)}, {‘name‘: ‘小二‘, ‘total‘: Decimal(‘689.33‘)}, {‘name‘: ‘小三‘, ‘total‘: Decimal(‘111.12‘)}, {‘name‘: ‘小四‘, ‘total‘: None}]>123
 
F查询
在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
查询书id大于\小于价格的书籍
 
models.Book.objects.filter(id__gt=F("price"))
<QuerySet []>
models.Book.objects.filter(id__lt=F("price"))
<QuerySet [<Book: 书一>, <Book: 书二>, <Book: 书三>, <Book: 书四>, <Book: 书五>, <Book: 书六>]>12345
Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
 

models.Book.objects.filter(id__lt=F("price")/2)
<QuerySet [<Book: 书一>, <Book: 书二>, <Book: 书三>, <Book: 书四>, <Book: 书五>]>12
修改操作也可以使用F函数,比如将每一本书的价格提高30元
 
models.Book.objects.all().update(price=F("price")+30)1
修改之后的截图如下:

Concat链接
 
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F("title"),Value("("),Value("第"),Value(")")))123
修改之后的表如下:
 

Q查询
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象
查询作者名是小仙女或小魔女的
 
models.Author.objects.filter(Q(name="小一") | Q(name="小三"))
<QuerySet [<Author: 小一>, <Author: 小三>]>
123
你可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询
查询作者名字是小仙女并且不是2018年出版的书的书名。
 
models.Book.objects.filter(Q(author__name="小一") & ~Q(publish_day__year=2018)).values_list("title")
<QuerySet [(‘书一‘,)]>12
查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将”AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面
 
models.Book.objects.filter(Q(publish_day__year=2018) | Q(publish_day__year=2017), title__icontains="书")
<QuerySet [<Book: 书一>, <Book: 书二>, <Book: 书三(第)>, <Book: 书四(第)>, <Book: 书五(第)>, <Book: 书六(第)>]>
123
 
总结
 
ORM 跨表查询
    class Book(models.Model):  
        title = models.CharField( max_length=32)
        publish=models.ForeignKey(to="Publish",to_field="id")
        authors=models.ManyToManyField(to=‘Author‘,related_name=‘bookList‘) 
    class Publish(models.Model):
        name=models.CharField( max_length=32)

    class Author(models.Model):
        name=models.CharField( max_length=32)
        ad=models.OneToOneField("AuthorDetail")
    class AuthorDetail(models.Model):
        telephone=models.BigIntegerField()

    基于对象查询(sql:子查询)

          一对多的关系  (Publish--Book)
                  正向查询,按字段:
                  查询python这本书的出版社所在的名称
                  book_obj=Book.objects.filter(title="python").first()
                  #print(book_obj.publish.name)
                  反向查询,按表名小写_set:
                  人民出版社出版过的所有书籍名称
                  publish_obj=Publish.objects.filter(name="人民出版社出版").first()
                  print(publish_obj.book_set.all()) 
                  for obj in publish_obj.book_set.all():
                       print(obj.title)

          多对多的关系
                正向查询,按字段:
                    python这本书所有作者的名字
                        book_obj=Book.objects.filter(title="python").first()
                        book_obj.authors.all()
                反向查询,按表名小写_set:
                    alex出版过的所有书籍名称
                    alex=Author.objects.filter(name="alex").first()
                    alex.bookList.all()
          一对一的关系
                正向查询,按字段:
                    查询alex的手机号
                    alex=Author.objects.filter(name="alex").first()
                    alex.ad.telephone
                反向查询:按表名小写
                    以151开头的手机号的作者的名字
                    ad=AuthorDetail.objects.get(telephone__startswith="151")
                    ad.author.name     

    基于Queryset和 __(sql:join语句):
          正向查询,按字段
          反向查询,按表名小写
          一对多的关系  (Publish--Book)

                  查询python这本书的所在出版社的名称
                  Book.objects.filter(title="python").values("publish__name")
                  for obj in Book.objects.filter(title="python"):
                      temp={}
                      temp["publish__name"]=obj.publish.name
                  人民出版社出版过的所有书籍名称        
                  Publish.objects.filter(name="人民出版社出版").values("book__title")
 
          多对多的关系
                    python这本书所有作者的名字
                        Book.objects.filter(title="python").values("authors__name")

                    alex出版过的所有书籍名称
                        Author.objects.filter(name="alex").values("book__title")

          一对一的关系
                    查询alex的手机号
                        Author.objects.filter(name="alex").values("ad__telephone")
                    以151开头的手机号的作者的名字
                    AuthorDetail.objects.filter(telephone__startswith="151").values("author__name")
         扩展:
                练习1:
                查询python这本书的所在出版社的名称
                Book.objects.filter(title="python").values("publish__name")         
                Publish.objects.filter(book__title="python").values("name")
                练习2:
                手机号以151开头的作者出版过的所有书籍名称以及出版社名称
                Book.objects.filter(authors__ad__telephone__startswith="151").values("title","publish__name")
    分组查询:
            查询每一个出版社出版过的书籍个数   
            Publish.objects.annotate(Count("book__id"))
            select count(*) from publish  group by id
————————————————
版权声明:本文为CSDN博主「进击的小猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013210620/java/article/details/79182038

django-聚合、分组、F查询和Q查询、总结

原文:https://www.cnblogs.com/xiaomahei/p/13110408.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!