多表查询
子查询
连表查询
一对多字段增删改查:
一对多字段增删改查
- models.Book.objects.create(title='三国演义',price=123.23,publish_id=1) # publish_id 直接传出版社主键值
- publish_obj = models.Publish.objects.filter(pk=2).first()
- models.Book.objects.create(title='水浒传',price=123.23,publish=publish_obj) # publish 直接传出版社数据对象
查
- book_obj = models.Book.objects.filter(pk=1).first()
- print(book_obj.publish) # 获取到当前所对应的出版社对象
- print(book_obj.publish_id) # 获取到的就是表中的实际字段
改
- models.Book.objects.filter(pk=1).update(publish_id=3)
- publish_obj = models.Publish.objects.filter(pk=2).first()
- models.Book.objects.filter(pk=1).update(publish=publish_obj)
删除
models.Publish.objects.filter(pk=2).delete()
默认也是级联更新 级联删除
多对多字段的增删改查:
给主键为 3 的书籍添加两个作者 1 2
- book_obj = models.Book.objects.filter(pk=3).first()
- print(book_obj.authors) # 就相当于 已经在书籍和作者的关系表了
- book_obj.authors.add(1)
- book_obj.authors.add(2,3)
- author_obj = models.Author.objects.filter(pk=1).first()
- author_obj1 = models.Author.objects.filter(pk=2).first()
- book_obj.authors.add(author_obj)
- book_obj.authors.add(author_obj,author_obj1)
- """
- add() 括号内既可以传数字也可以传数据对象
- 并且都支持传多个
- """
修改关系
- book_obj = models.Book.objects.filter(pk=3).first()
- book_obj.authors.set([3,])
- book_obj.authors.set([1,3])
- author_obj = models.Author.objects.filter(pk=1).first()
- author_obj1 = models.Author.objects.filter(pk=2).first()
- book_obj.authors.set((author_obj,))
- book_obj.authors.set((author_obj,author_obj1))
- """
- set() 括号内 既可以传数字也传对象
- 并且也是支持传多个的
- 但是需要注意 括号内必须是一个可迭代对象
- """
删
- book_obj = models.Book.objects.filter(pk=3).first()
- book_obj.authors.remove(2)
- book_obj.authors.remove(1,2)
- author_obj = models.Author.objects.filter(pk=1).first()
- author_obj1 = models.Author.objects.filter(pk=2).first()
- book_obj.authors.remove(author_obj)
- book_obj.authors.remove(author_obj,author_obj1)
- """
- remove() 括号内 既可以传数字也传对象
- 并且也是支持传多个的
- """
清空
- book_obj = models.Book.objects.filter(pk=3).first()
- book_obj.authors.clear()
- """clear() 括号内不需要传任何参数 直接清空当前书籍对象所有的记录"""
- """
- ORM 跨表查询
- 1. 子查询
- 2. 连表查询
- 正反向的概念
- 外键字段在谁那儿 由谁查谁就是正向
- 谁手里有外键字段 谁就是正向查
- 没有外键字段的就是反向
- 书籍对象 查 出版社 外键字段在书籍 正向查询
- 出版社 查 书籍 外键字段在书籍 反向查询
- 正向查询按字段
- 反向查询按表名小写 ...
- """
简而言之, 就是我手里有主键字段, 要去查你, 就是正向查询, 你来查我, 就是反向查询.
"""
正向查询 按字段
当该字段所对应的数据有多个的时候 需要加. all()
否者点外键字段直接就能够拿到数据对象
"""
1. 基于对象的跨表查询 子查询
1. 查询书籍是 python 入门的出版社名称
- book_obj = models.Book.objects.filter(title='python 入门').first()
- # 正向查询按字段
- print(book_obj.publish.name)
- print(book_obj.publish.addr)
2. 查询书籍主键是 6 的作者姓名
- book_obj = models.Book.objects.filter(pk=6).first()
- # print(book_obj.authors) # app01.Author.None
- print(book_obj.authors.all())
3. 查询作者是 jason 的手机号
- author_obj = models.Author.objects.filter(name='jason').first()
- print(author_obj.author_detail.phone)
- print(author_obj.author_detail.addr)
- """
- 反向查询按表名小写
- 什么时候需要加_set
- 当查询的结果可以是多个的情况下 需要加_set.all()
- 无论你的查询结果有几个, 只要他存在多个的情况, 就要加
- 什么时候不需要加_set
- 当查询的结果有且只有一个的情况下 不需要加任何东西 直接表名小写即可
- """
4. 查询出版社是东方出版社出版过的书籍
- publish_obj = models.Publish.objects.filter(name='东方出版社').first()
- # print(publish_obj.book_set) # app01.Book.None
- print(publish_obj.book_set.all())
5. 查询作者是 jason 写过的所有的书
- author_obj = models.Author.objects.filter(name='jason').first()
- # print(author_obj.book_set) # app01.Book.None
- print(author_obj.book_set.all())
6. 查询手机号是 110 的作者
- author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
- print(author_detail_obj.author)
- print(author_detail_obj.author.name)
- print(author_detail_obj.author.age)
基于双下划线的跨表查询 连表查询
1. 查询书籍是 python 入门的出版社名称
正向
- res = models.Book.objects.filter(title='python 入门').values('publish__name')
- print(res)
反向 (这才是真正的反向查询, 要什么就应该在什么表里查)
- res = models.Publish.objects.filter(book__title='python 入门').values('name')
- print(res)
2. 查询作者是 jason 的手机号码
正向
- res1 = models.Author.objects.filter(name='jason').values('author_detail__phone')
- print(res1)
反向
- res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
- print(res)
3. 查询手机号是 120 的作者姓名
- res2 = models.AuthorDetail.objects.filter(phone=120).values('author__name')
- print(res2)
- res = models.Author.objects.filter(author_detail__phone=120).values('name','author_detail__addr')
- print(res)
4. 查询出版社是东方出版社出版的书籍名称
- res = models.Publish.objects.filter(name='东方出版社').values('book__title','addr')
- print(res)
5. 查询作者是 jason 的写过的书的名字和价格
- res = models.Author.objects.filter(name='jason').values('book__title','book__price')
- print(res)
7. 查询书籍是 python 入门的作者的手机号
- res = models.Book.objects.filter(title='python 入门').values('authors__author_detail__phone')
- print(res)
解释一下上面的第七题, 也就是最后一题.
我们要查询的是作者的手机号, 在 Book 表里面没有这个字段, 而且 Book 表也没法直接和作者详情表有联系, 所以要通过中间的一张表也就是作者表, 首先查询书籍名称是 python 入门的书, 然后通过 values 来取字段的值, 书籍查找作者是正向查询, 所以直接通过字段名来查询就好了, 这里括号中写出 authors 的时候, 已经跨到作者表了 (因为 authors 是外键字段), 然后双下划綫 author_detail, 就跨到了作者详情表, 然后在通过双下滑想取到了 phone 的值.
也就是说:
只要表与表之间有外键的联系, 可以通过无限的双下划綫跨越无数张表去查询数据
讲了这么多, 简单的总结一下.
正向查询: 也就是外键在我这边, 我查找你, 直接像这样就可以了
查询名叫 python 入门的书的出版社
- book_obj = models.Book.objects.filter(title='python 入门').first()
- # 也可以写成 book_obj = models.Book.objects.filter(title='python 入门').values(publish__name)
- # 正向查询按字段
- print(book_obj.publish) #publish 是外键, 直接就可以拿到这个 publish 对象.
- print(book_obj.publish.addr)# 可以直接就点出属性了
方向查询: 外键在你那边, 我查找你, 原本写法如下
查询出版社是东方出版社出版过的书籍
- publish_obj = models.Publish.objects.filter(name='东方出版社').first()
- print(publish_obj.book_set.all())# 外键在对面, 你就是一的那一边, 查找结果一定是可以存在多个的, 所以加_set 就好了
后来学了双下划綫, 就如下了
查询名叫 python 入门的书的出版社名称
- res=models.Book.objects.filter(publish__name='东方出版社').values('title')
- # 因为是反向查询, 所以只用写表的名字的小写就可以了, 写了 publish 之后就相当于跨表到了 publish 表, 双下划綫就拿到了 name.
多表查询
来源: http://www.bubuko.com/infodetail-3260202.html