ORM的查询操作
查询的分类
1 class Author(models.Model): 2 name = models.CharField(max_length=32) 3 age = models.IntegerField() 4 5 # 与AuthorDetail建立一对一的关系 6 ad = models.OneToOneField(to="AuthorDetail") 7 8 class AuthorDetail(models.Model): 9 birthday = models.DateField() 10 telephone = models.BigIntegerField() 11 addr = models.CharField(max_length=64) 12 13 class Publish(models.Model): 14 name = models.CharField(max_length=32) 15 city = models.CharField(max_length=32) 16 email = models.EmailField() 17 18 19 class Book(models.Model): 20 21 title = models.CharField(max_length=32) 22 publishDate = models.DateField() 23 price = models.DecimalField(max_digits=5, decimal_places=2) 24 keepNum = models.IntegerField() 25 commentNum = models.IntegerField() 26 27 # 与Publish建立一对多的关系,外键字段建立在多的一方 28 publish = models.ForeignKey(to="Publish", to_field="nid") 29 30 # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任 31 #意一个,自动创建第三张表 32 authors = models.ManyToManyField(to='Author') 33 34 35 三个关联字段: 36 37 # 与AuthorDetail建立一对一的关系 38 ad = models.OneToOneField(to="AuthorDetail") 39 40 # 与Publish建立一对多的关系,外键字段建立在多的一方 41 publish = models.ForeignKey(to="Publish", to_field="nid") 42 43 # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的 任意一个,自动创建第三张表 44 authors = models.ManyToManyField(to='Author')
基于对象的查询(子查询)
查询思想:
首先得到一个对象,通过此对象进行正向查询或者反向查询。
使用条件:
使用的前提必须是一个对象,在一对多与多对多的环境下才能使用对象.表名小写_set().all();在一对一的环境下,使用对象.表明小写
一对一
正向按照字段:对象.外键字段.字段
表一---------------------------->表二
表一<----------------------------表二
反向按照表名:对象.表名小写.字段
示例:
1 #查询作者阿童木的邮箱地址(正向) 2 auth_obj = Author.objects.filter(name="阿童木").first() 3 print(auth_obj.detail.email) 4 5 #查询邮箱以“1”开头的坐着的姓名(反向) 6 detail_obj = Author_detail.objects.filter(email__startswith="1").first() 7 print(detail_obj.author.name)
注意:
在一对一的关系中,不管是正向还是反向查询得到的只能是一个结果,因此不需要加"_"。
但是在一对多或多对多的关系中,一 的一方找多的一方,正向使用"对象.字段"的格式进入另一张表,反向使用“对象.表名小写_set”进入另一张表。
一对多
正向按照字段:对象.外键字段.字段
表一---------------------------->表二
表一<----------------------------表二
反向按照表名小写:对象.表名小写_set.字段
示例:
1 #查询“葵花宝典”这本书的出版社的名称(正向) 2 book_obj = Book.objects.filter(title="葵花宝典").first() 3 book_obj.publisher.name 4 5 #查询“北京邮电出版社”出版的所有书籍的名称(反向) 6 publish_obj = Publish.objects.filter(name="北京邮电出版社").first() 7 publish_obj.book_set.values("title")
多对多
正向按照字段
表一---------------------------->表二
表一<----------------------------表二
反向按照表名小写_set()
示例:
1 #查询“葵花宝典”这本书的所有作者的姓名和年龄(正向) 2 book_obj = Book.objects.filter(title="葵花宝典").first() 3 book_obj.author.all().values("name","age") 4 5 #查询“阿童木”所出版的所有书的名称和价格(反向) 6 author_obj = Author.objects.filter(name="阿童木").first() 7 author_obj.book_set.all().values("title","price")
基于Queryset的查询(连表查询)
注意:
在使用基于QuerySet的双下划线进行查询的时候,不管是一对一,一对多还是多对多,都使用表名小写__字段。
一对一
正向按照字段:Queryset.values("外键字段__字段")
表一---------------------------->表二
表一<----------------------------表二
反向按照表名:Queryset.values("表名小写__字段")
示例:
1 #查询作者为“阿童木”的邮箱地址(正向) 2 Author.objects.filter(name="阿童木").values("detail__email") 3 4 #查询邮箱以“1”开头的作者姓名 5 Author_detail.objects.filter(email__startswith="1").values("author__name")
一对多
正向按照字段:对象.外键字段.字段
表一---------------------------->表二
表一<----------------------------表二
反向按照表名:Queryset.values("表名小写__字段")
示例:
1 #查询"葵花宝典"这本书的出版社的名称和所在城市(正向) 2 Book.objects.filter(title="葵花宝典").values("publisher__name","publisher__city") 3 4 #查询“北京邮电出版社”所出版的所有书籍的名称和价格(反向) 5 Publish.objects.filter(name="北京邮电出社").values("book__title","book__price")
多对多
正向按照字段:对象.外键字段.字段
表一---------------------------->表二
表一<----------------------------表二
反向按照表名:Queryset.values("表名小写__字段")
示例:
1 #查询“葵花宝典”这本书的作者名称和email(正向,两次跨表) 2 Book.objects.filter(title="葵花宝典").values("author__name","author__detail__email") 3 4 #查询阿童木的出版的所有书籍的名称和价格(反向) 5 Author.objects.filter(name="阿童木").values("book__title","book__price")
聚合
1 from django.db.models import Avg,Sum,Count,Max,Min 2 # 1、查询所有图书的平均价格 3 print(models.Book.objects.all().aggregate(Avg("price")))
aggregate()是QuerySet 的一个终止子句(也就是返回的不再是一个QuerySet集合的时候),意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。
1 # 1、查询所有图书的平均价格 2 print(models.Book.objects.all().aggregate(avgprice = Avg("price")))
如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
1 print(models.Book.objects.all().aggregate(Avg("price"),Max("price"),Min("price"))) 2 #打印的结果是: {'price__avg': 174.33333333333334, 'price__max': Decimal('366.00'), 'price__min': Decimal('12.00')}
分组
1 #查询每一个出版社出版过的书籍数量和出版社名称 2 Publish.objects.all().annotate(c=Count("book")).values("name","c")