八、Django的orm之多表操作(二)

一、查询(重点)

  1. 基于对象的跨表查询 -- 类似于子查询

正向查询和反向查询

关系属性(字段)写在哪个表里面,从当前类(表)的数据去查询它关联类(表)的数据叫做正向查询,反之叫做反向查询

  • 一对一查询

    • 正向查询
      # 1.查询jiege的地址
      author_obj = models.Author.objects.get(name=‘jiege‘)
      print(author_obj.authorDetail.addr)

      # 或者用filter这种查,但是要加.first()变成models对象,否则报错
      author_obj1 = models.Author.objects.filter(name='jiege').first()
      print(author_obj1.authorDetail.addr)
      
      # 正向 author_obj.authorDetail 也就是 对象.关联属性名称
    • 反向查询
      # 2.查询 1996-02-14 是谁的生日
      authordetail_obj = models.AuthorDetail.objects.get(birthday=‘1996-02-14‘)
      print(authordetail_obj.author.name)

      # 反向 authordetail_obj.author  也就是 对象.小写的另一个表名(类名)
    • 总结
      Author表 一对一关联 AuthorDetail表

             正向查询:Authorobj.authorDetail,对象.关联属性名称
      Author------------------------------------------------->AuthorDetail
           <-------------------------------------------------
             反向查询:AuthorDetailobj.author  ,对象.小写类名
  • 一对多的查询
    注:关系字段在哪个表,哪个表就是“多“,被关联的表是”一“

    • 正向查询
      # 1.查询 回村的诱惑 这本书是哪个出版社出版的
      book_obj = models.Book.objects.get(title=‘回村的诱惑‘)
      print(book_obj.publish.name)

      # 正向 book_obj.publish  也就是 对象名.关联属性名称
    • 反向查询
      # 2.查询 外交出版社 都出版了哪些书
      publish_obj = models.Publish.objects.get(name=‘外交出版社‘)
      print(publish_obj.book_set.all()) # <QuerySet [<Book: yuhao的回忆录>, <Book: 杰哥你真猛>]>
      print(publish_obj.book_set.all().filter(price__gt=500)) # <QuerySet [<Book: 杰哥你真猛>]>

      # 反向 publish_obj.book_set  也就是 对象.表名小写_set
      # 因为一个出版社可以对应很多书,所以用 book_set
      # 因为结果返回一个queryset对象,可以继续加 .方法
    • 总结
      Book表 一对多关联 Publish表

             正向查询:book_obj.publish,对象.关联属性名称
      Book -------------------------------------------------> Publish
           <-------------------------------------------------
             反向查询:publish_obj.book_set.all(),对象.表名小写_set
  • 多对多的查询
    • 正向查询
      # 1.查询 yuhao的回忆录 这本书的作者都有谁
      book_obj = models.Book.objects.get(title=‘yuhao的回忆录‘)
      print(book_obj.authors.all()) # <QuerySet [<Author: jiege>, <Author: yuhao>, <Author: liangdao>]>

      # 正向 book_obj.authors.all() 就是 对象.属性
    • 反向查询
      # 2.查询 liangdao 都写过哪些书
      author_obj = models.Author.objects.get(name=‘liangdao‘)
      print(author_obj.book_set.all()) # <QuerySet [<Book: yuhao的回忆录>, <Book: 装13是如何炼成的2>]>

      # 反向 book_obj.author_obj.book_set.all()  就是 对象.表名小写_set
    • 总结
      Book表 多对多关联 Author表

             正向查询:book_obj.authors.all(),对象.关联属性名称
      Book -------------------------------------------------> Author
           <-------------------------------------------------
             反向查询:author_obj.book_set.all(),对象.表名小写_set
  1. 基于双下划线的跨表查询 -- 类似连表join

正向查询和反向查询

  • 一对一

    • 查询 jiege 的地址
      # 方式1:正向查询
      obj = models.Author.objects.filter(name=‘jiege‘).values(‘authorDetail__addr‘)
      print(obj) # <QuerySet [{‘authorDetail__addr‘: ‘天空之城‘}]>

      # 方式2:反向查询
      obj1 = models.AuthorDetail.objects.filter(author__name='jiege').values('addr')
      print(obj1) # <QuerySet [{'addr': '天空之城'}]>
    • 哪个作者的生日是 2019 - 07 - 19
      # 方式1:正向查询
      obj = models.Author.objects.filter(authorDetail__birthday=‘2019-07-19‘).values(‘name‘)
      print(obj) # <QuerySet [{‘name‘: ‘liangge‘}]>

      # 方式2:反向查询
      obj1 = models.AuthorDetail.objects.filter(birthday='2019-07-19').values('author__name')
      print(obj1)  # <QuerySet [{'author__name': 'liangge'}]>
  • 一对多
    • 查询一下 装13是如何炼成的 这本书的出版社是哪个
      # 方式1:正向查询
      obj = models.Book.objects.filter(title=‘装13是如何炼成的‘).values(‘publish__name‘)
      print(obj) # <QuerySet [{‘publish__name‘: ‘膨胀出版社‘}]>

      # 方式2:反向查询
      obj1 = models.Publish.objects.filter(book__title='装13是如何炼成的').values('name')
      print(obj1)  # <QuerySet [{'name': '膨胀出版社'}]>
    • 膨胀出版社 出版了哪些书
      # 方式1:正向查询
      obj = models.Book.objects.filter(publish__name=‘膨胀出版社‘).values(‘title‘)
      print(obj)
      # <QuerySet [{‘title‘: ‘装13是如何炼成的‘}, {‘title‘: ‘回村的诱惑‘}, {‘title‘: ‘装13是如何炼成的2‘}, {‘title‘: ‘杰哥诱惑‘}]>

      # 方式2:反向查询
      obj1 = models.Publish.objects.filter(name='膨胀出版社').values('book__title')
      print(obj1)
      # <QuerySet [{'book__title': '装13是如何炼成的'}, {'book__title': '回村的诱惑'}, {'book__title': '装13是如何炼成的2'}, {'book__title': '杰哥诱惑'}]>
  • 多对多
    • 杰哥诱惑 这本书是谁写的
      # 方式1:正向查询
      obj = models.Book.objects.filter(title=‘杰哥诱惑‘).values(‘authors__name‘)
      print(obj) # <QuerySet [{‘authors__name‘: ‘yuhao‘}]>

      # 方式2:反向查询
      obj1 = models.Author.objects.filter(book__title='杰哥诱惑').values('name')
      print(obj1)  # <QuerySet [{'name': 'yuhao'}]>
    • yuhao 都写了哪些书
      # 方式1:正向查询
      obj = models.Book.objects.filter(authors__name=‘yuhao‘).values(‘title‘)
      print(obj)
      # <QuerySet [{‘title‘: ‘装13是如何炼成的‘}, {‘title‘: ‘yuhao的回忆录‘}, {‘title‘: ‘装13是如何炼成的2‘}, {‘title‘: ‘杰哥诱惑‘}]>

      # 方式2:反向查询
      obj1 = models.Author.objects.filter(name='yuhao').values('book__title')
      print(obj1)
      # <QuerySet [{'book__title': '装13是如何炼成的'}, {'book__title': 'yuhao的回忆录'}, {'book__title': '装13是如何炼成的2'}, {'book__title': '杰哥诱惑'}]>
  • 进阶
    • 装13出版社 出版的书的名称以及作者的名字
      # 关联了三张表,Book、Author、publish

      方式一:
          obj = models.Publish.objects.filter(name='装13出版社').values('book__title','book__authors__name')
          print(obj)
          # <QuerySet [{'book__title': '回娘家的诱惑', 'book__authors__name': 'jiege'}, {'book__title': '回娘家的诱惑', 'book__authors__name': 'yuhao'}]>
      
      方式二:
          obj1 = models.Book.objects.filter(publish__name='装13出版社').values('title','authors__name')
          print(obj1)
          # <QuerySet [{'title': '回娘家的诱惑', 'authors__name': 'jiege'}, {'title': '回娘家的诱惑', 'authors__name': 'yuhao'}]>
      
      方式三:
          obj2 = models.Author.objects.filter(book__publish__name='装13出版社').values('book__title','name')
          print(obj2)
          # <QuerySet [{'book__title': '回娘家的诱惑', 'name': 'jiege'}, {'book__title': '回娘家的诱惑', 'name': 'yuhao'}]>

      原生的sql语句是这样的:
      SELECT
      app01_book.title,
      app01_author.name
      FROM
      app01_publish
      INNER JOIN app01_book ON app01_publish.nid = app01_book.publish_id
      INNER JOIN app01_book_authors ON app01_book.nid = app01_book_authors.book_id
      INNER JOIN app01_author ON app01_author.nid = app01_book_authors.author_id
      WHERE
      app01_publish.name = ‘装13出版社‘;
      使用Navicat工具:

    • 手机号以4开头的作者出版过的所有书籍名称以及出版社名称
      # 关联了四张表,Book、Author、publish、AuthorDetail

      # 方式一
          obj = models.AuthorDetail.objects.filter(telephone__startswith='4').values('author__book__title','author__book__publish__name')
          print(obj)
      
      # 方式二
          obj1 = models.Book.objects.filter(authors__authorDetail__telephone__startswith='4').values('title','publish__name')
          print(obj1)
      
      # 方式三
          obj2 = models.Publish.objects.filter(book__authors__authorDetail__telephone__startswith='4').values('book__title','name')
          print(obj2)
      
      # 方式四
          obj3 = models.Author.objects.filter(authorDetail__telephone__startswith='4').values('book__title','book__publish__name')
          print(obj3)

3.related_name

反向查询时,如果定义了related_name ,则用related_name替换 表名,

注意:,用在外键的创建 ForeignKey 中的一个参数,只会影响反向查询

例如:

# 在创建Book表的时候

class Book(models.Model):
    ......
    publish=models.ForeignKey(to="Publish", to_field = "nid", on_delete = models.CASCADE,related_name='xx')
    ......

# 因为定义了related_name='xx',所以
    # 在正向查询时,不会影响什么
    # 在反向查询时,就不会用小写的表名了,而是必须用'xx',否则会报错

比如查询 装13是如何炼成的 这本书的出版社的名字
正向查询:
    obj = models.Book.objects.filter(title='装13是如何炼成的').values('publish__name')
    print(obj)
反向查询:
    # 没加related_name='xx'
    obj1 = models.Publish.objects.filter(book__title='装13是如何炼成的').values('name')
    print(obj1)
    # 加入了related_name='xx'
    obj1 = models.Publish.objects.filter(xx__title='装13是如何炼成的').values('name')
    print(obj1)

二、聚合查询

  1. 聚合

计算所有图书的平均价格、最高价格

from django.db.models import Avg,Max,Min,Count
obj = models.Book.objects.all().aggregate(a=Avg('price'),m=Max('price'))
print(obj)  # {'a': 411.998571, 'm': Decimal('998.00')}

注意点:

  • aggregate()是QuerySet 的一个终止子句,得到的是个字典
  • 字典通过键取值,得到的是一个数字,可直接用于计算
    print(obj[‘m‘] - 2) #{‘price__avg‘: 2.833333}

原文地址:https://www.cnblogs.com/yangzm/p/11241117.html

时间: 2024-11-09 03:25:29

八、Django的orm之多表操作(二)的相关文章

ORM之连表操作

ORM之连表操作 UserInfo和UserType两个表关联,UserInfo的外键连UserType的主键.拿到UserInfo的所有信息,就可以拿与UserInfo相关联的UserType的数据. result = model.UserInfo.object.all() 与UserInfo有关联的UserType表: for obj in result: print(obj.name,obj,age,obj.ut_id,obj.ut_title) #ut_id是UserType表的id,u

Django模型层之单表操作

Django模型层之单表操作 一 .ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软件,例如mysql.oracle.Microsoft SQL Server等. 如果应用程序需要操作数据(比如将用户注册信息永久存放起来),那么我们需要在应用程序中编写原生sql语句,然后使用pymysql模块远程操作mysql数据库,详见图一^①^ 但是直接编写原生sql语句会存在两方面的问题,严

Django开发:(3.1)ORM:单表操作

MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动 ORM是"对象-关系-映射"的简称. Mysql中的表对应python中的类,表的字段对应类的属性,表的记录对应类的实例化的对象 单表操作 创建表 1. 创建模型 创建名为app01的app,在app01下的models.py中创建模型: from dj

Django基础五之django模型层(一)单表操作

目录 一 ORM简介 二 单表操作 一.创建表 创建模型 2 更多字段和参数 3 settings配置 4.自定义字段(了解) 二.添加表纪录 方式1 方式2(用的多) 方式3:批量插入 三.查询表纪录 查询API(都是重点) 基于双下划线的模糊查询 四.删除表纪录 五.修改表纪录 三 章节作业 1 图书管理系统 2 查询操作练习 四 xxx 本节目录 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,

django 利用ORM对单表进行增删改查

牛小妹上周末,一直在尝试如何把数据库的数据弄到界面上.毕竟是新手,搞不出来,文档也看不懂.不过没关系,才刚上大学.今晚我们就来解释下,要把数据搞到界面的第一步.先把数据放到库里,然后再把数据从库里拿出来. 以下内容,参考django官方文档 . 1.创建MODEL 这里和官方文档一致.直接拷出来,放到一个叫models的py文件里面.若是你的项目中没有,一定不要觉得无处写代码.你自己建一个即可 同步数据库: 执行以下命令.不懂的可以参考:django连接mysql python manage.p

web框架开发-Django模型层(2)-多表操作

很重要,都是精华 多表关系模型 一对一 一旦确定表关系是一对一,在两张表中的任意一张表中建立关联字段+Unique 一对多 一旦确定表关系是一对多,创建关联字段在多的表中 多对多 一旦确定表关系是多对多,创建第三章关系表 ORM生成关系表模型 假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关系(one-to-one) 出版商模型:出版商有名称,所在城市以及email. 书

Django模型层之多表操作

作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关系(one-to-one) 出版商模型:出版商有名称,所在城市以及email. 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many). 具体的模型如下:(models.

Django之模型层-多表操作

多表操作 数据库表关系 一对多:两个表之间的关系一旦确定为一对多,必须在数据多的表中创建关联字段 多对多:两个表之间的关系一定确定为多对多,必须创建第三张表(关联表) 一对一:一旦两个表之间的关系确定为一对一,在两种表中任意一张表中建立关联字段unique ORM生成关联表模型 class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=32) pric

django模型层2 多表操作

1.多表操作: 1.创建模型: 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关系(one-to-one) 出版商模型:出版商有名称,所在城市以及email. 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一