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")
原文地址:https://www.cnblogs.com/liuyinzhou/p/8502744.html