zoukankan      html  css  js  c++  java
  • python之路_django ORM模型(联表)(二)

    一、基于双下划线跨表查询(join查询)

      在上一篇中,我们简单的介绍了基于对象的跨表查询,本章将继续阐述基于双下划线的跨表查询,所用的表格均为上章中所创建的表格。

    ###############基于双下划线的查询:正向查询,按字段,反向查询,按表名###############

    1、一对多

    实例一(正向,用字段):

    # 查询红楼梦的出版社名称
    #方式1:
    ret=Book.objects.filter(title="红楼梦").values("publish__name")           
    print(ret)                                                          # <QuerySet [{'publish__name': '北京出版社'}]>
    # 方式2:
    res=Publish.objects.filter(book__title="红楼梦").values("name")          
    print(res)                                                          #<QuerySet [{'name': '北京出版社'}]>

    实例二(反向,用表名):

    # 查询沙河出版社出版过的书籍名称
    #方式1:
    ret=Publish.objects.filter(name="沙河出版社").values("book__title")
    print(ret)                                                         #<QuerySet [{'book__title': '金品梅2'}, {'book__title': '金品梅3'}]>
    #方式2:
    res=Book.objects.filter(publish__name="沙河出版社").values("title")
    print(res)                                                         #<QuerySet [{'title': '金品梅2'}, {'title': '金品梅3'}]>

    2、多对多

    实例一(正向,用字段):

    # 查询红楼梦所有作者的名字
    ret=Book.objects.filter(title="红楼梦").values("authors__name")
    print(ret)                                                        #<QuerySet [{'authors__name': 'alex'}, {'authors__name': 'egon'}]>

    实例二(反向,用表名):

    #查询alex出版过的所有书籍
    ret=Author.objects.filter(name="alex").values("book__title")
    print(ret)                                                        #<QuerySet [{'book__title': '金品梅2'}, {'book__title': '红楼梦'}]>

    3、一对一

    实例一(正向,用字段):

    # 查询地址在沙河并且email是123的作者的名字
    ret=AuthorDetail.objects.filter(adrr="沙河",email=123).values("author__name")
    print(ret)                                                        #<QuerySet [{'author__name': 'alex'}]>

    实例二(反向,用表名):

    # 查询alex作者的adrr地址
    ret = Author.objects.filter(name="alex").values("authordetail__adrr")
    print(ret)                                                       #<QuerySet [{'authordetail__adrr': '沙河'}]>

    实例三(综合实例):

    #email以456开头的作者出版过的所有书籍名称以及出版社名称  
    ret=Book.objects.filter(authors__authordetail__email__startswith="456").values("title","publish__name")
    print(ret)

      总结,在上一章的对象查询中,我们可以总结为所有的查询是基于一个models对象,而本节中双下划线查询均是基于queryset对象进行的!反向查询使用的表名同样必须为小写。

    二、聚合函数(aggregate)

      aggregate()QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。如下例:

    #查询所有书籍的平均价格
    # 实例1:
    ret=Book.objects.all().aggregate(Avg("price"))
    print(ret)                                                         #{'price__avg': 172.66666666666666}
    # 实例2:
    res = Book.objects.all().aggregate(avgPrice=Avg("price"))
    print(res)                                                         #{'avgPrice': 172.66666666666666}

      如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

    # 查询所有书籍的平均价格、价格最大值、价格最小值
    ret = Book.objects.all().aggregate(Avg("price"),Min("price"),Max("price"))
    print(ret)                         #{'price__avg': 172.66666666666666, 'price__min': Decimal('123.00'), 'price__max': Decimal('230.00')}

      以上实例中需要按照如下方式引入相应的模块方法: from django.db.models import Avg, MaxMin

    三、分组函数(annotate)

      annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

      实例1:查询每一个出版社出版过的书籍个数

    ret=Publish.objects.all().annotate(num=Count("book__title"))     #可以理解为每一个出版社对象增加一个num字段,该字段值是通过聚合函数联表求得
    for pub_obj  in ret:
        print(pub_obj.name,pub_obj.num)

      annotate的返回值是querySet,如果不想遍历对象,可以用上values_list,如下:

    ret = Publish.objects.all().annotate(num=Count("book__title")).values_list("name","num")
    print(ret)                                                       #<QuerySet [('人民出版社', 0), ('沙河出版社', 2), ('北京出版社', 1)]>

      实例2:查询每一本书的作者个数

    ret=Book.objects.all().annotate(counts=Count("authors__nid")).values("title","counts")
    print(ret)        #<QuerySet [{'title': '金品梅2', 'counts': 2}, {'title': '金品梅3', 'counts': 2}, {'title': '红楼梦', 'counts': 2}]>

     四、练习题解析

      如下例为1-5分别使用基于对象查询和双下划线查询:

    # 1、查询人民出版社出版过的价格大于100的书籍的作者的email
    # 方法一:
    pub_obj = Publish.objects.get(name="人民出版社")
    book_obj = pub_obj.book_set.filter(price__gt=100)
    for book in book_obj:
    print(book.authors.all())
    for author in book.authors.all():
        print(author.authordetail.email)
    #方法二:
    pub_obj=Publish.objects.get(name="人民出版社")
    ret=pub_obj.book_set.filter(price__gt=100).values("authors__authordetail__email")
    print(ret)
    # 2、查询alex出版过的所有书籍的名称以及书籍的出版社的名称
    #方法1:
    book_obj=Author.objects.get(name="alex").book_set.all()
    for book in book_obj:
    print(book.title,book.publish.name)
    # 方法2:
    ret=Book.objects.filter(authors__name="alex").values("title","publish__name")
    print(ret)
    # 3、查询2011年出版社过的所有书籍的作者名字以及出版社名称
    #方法一:
    book_obj= Book.objects.filter(publishDate__year=2011)
    for book in book_obj:
    print(book.authors.all().values("name"),book.publish.name)
    #方法二:
    ret=Book.objects.filter(publishDate__year=2011).values("authors__name","publish__name")
    print(ret)
    # 4、查询住在沙河并且email以123开头的作者写过的所有书籍名称以及书籍的出版社名称
    #方法一:
    book_obj=AuthorDetail.objects.get(adrr="沙河", email__startswith=123).author.book_set.all()
    for book in book_obj:
    print(book.title,book.publish.name)
    
    #方法二:
    ret=AuthorDetail.objects.filter(adrr="沙河",email__startswith=123).values("author__book__title","author__book__publish__name")
    print(ret)
    # 5、查询年龄大于20岁的作者在哪些出版社出版过书籍
    #方法一:
    author_obj = Author.objects.filter(age__gt=20)
    for author in author_obj:
    # print(author.book_set.all())
    for book in author.book_set.all():
        print(book.publish.name)
    #方法二:
    ret=Author.objects.filter(age__gt=20).values("book__authors__name","book__publish__name")
    print(ret)
    
    # 6、查询每一个出版社的名称以及出版过的书籍个数
    ret=Publish.objects.all().annotate(counts=Count("book__nid")).values("name","counts")
    print(ret)
    # 7、查询每一个作者的名字以及出版过的所有书籍的最高价格
    ret=Author.objects.all().annotate(max_price=Max("book__price")).values("name","max_price")
    print(ret)
    # 8、查询每一本书的名字,对应出版社名称以及作者的个数
    ret=Book.objects.all().annotate(counts=Count("authors__nid")).values("title","publish__name","counts")
    print(ret)

    五、F查询与Q查询

      具体介绍如下:

    1、F查询

    2、Q查询

  • 相关阅读:
    Two Sum II
    Subarray Sum
    Intersection of Two Arrays
    Reorder List
    Convert Sorted List to Binary Search Tree
    Remove Duplicates from Sorted List II
    Partition List
    Linked List Cycle II
    Sort List
    struts2结果跳转和参数获取
  • 原文地址:https://www.cnblogs.com/seven-007/p/8024189.html
Copyright © 2011-2022 走看看