子查询(基于对象的跨表查询)
生成多表的准备工作已经在博客[Django-ORM模型层语法(四)之多表操作准备工作]中写了,各位可以点击下方的链接,跟着操作:
app01_author表 :
id | name | age | author_detail_id |
---|---|---|---|
1 | Kevin | 18 | 1 |
2 | Steven | 20 | 2 |
3 | Adam | 28 | 3 |
app01_book表 :
id | title | price | publish_date | publishs_id |
---|---|---|---|---|
1 | 红楼梦 | 66 | 2020-02-02 | 2 |
2 | 聊斋 | 100 | 2020-02-02 | 1 |
3 | 论语 | 200 | 2020-02-02 | 2 |
4 | 三国演义 | 300 | 2020-02-02 | 1 |
5 | 老子 | 400 | 2020-02-02 | 2 |
app01_authordetail表 :
| id |phone|addr|
|–|–|–|–|
| 1 |100| 南京|
| 2 |200| 北京|
| 3 |300| 深圳|
app01_pulish表 :
id | name | addr | |
---|---|---|---|
1 | 东方出版社 | 东方 | 123@qq.com |
2 | 西方出版社 | 西方 | 666@qq.com |
app01_book_authors表 :
| id |book_id|author_id|
|–|–|–|–|
| 1 |1| 1|
| 2 |1| 2|
| 3 |2| 1|
| 4 |2| 3|
| 5|3| 1|
| 6|3| 2|
| 7|3| 3|
正向查询
app01/tests.py
"""
当你只是想测试django中的某一个py文件内容 那么你可以不用书写前后端交互的形式
而是直接写一个测试脚本即可
脚本代码无论是写在应用下的tests.py还是自己单独开设py文件都可以
"""
# 测试环境的准备 去manage.py中拷贝前四行代码 然后自己写两行
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm1.settings")
import django
django.setup()
# 在这个代码块的下面就可以测试django里面的单个py文件了
# 所有的代码都必须等待环境准备完毕之后书写
from app01 import models
# 1.查询书籍主键为1的出版社
book_obj = models.Book.objects.filter(pk=1).first()
# 通过书查出版社(正向)
res = book_obj.publishs
print(res)
# 2.查询书籍主键为1的作者
book_obj = models.Book.objects.filter(pk=1).first()
# 通过书查作者(正向)
# res = book_obj.authors # app01.Author.None
res = book_obj.authors.all() # <QuerySet [<Author: Author object>, <Author: Author object>]>
print(res)
# 3.查询作者Steven的电话号码
author_obj = models.Author.objects.filter(name='Steven').first()
res = author_obj.author_detail
print(res)
print(res.phone)
'''
在书写orm语句的时候跟写sql语句是一样的,不要企图一次性将orm语句写完,如果比较复杂,就写一点看一点
正向什么时候需要加.all()
当你的结果可能是多个的时候,就需要.all()
如果是一个则直接拿到数据对象
book_obj.publishs
book_obj.authors.all()
author_obj.author_detail
'''
反向查询
app01/tests.py
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm1.settings")
import django
django.setup()
from app01 import models
# 4.查询东方出版社出版的书
publish_obj = models.Pulish.objects.filter(name='东方出版社').first()
# 通过出版社查书 反向
res = publish_obj.book_set # app01.Book.None
res = publish_obj.book_set.all()
print(res)
# 5.查询作者是Steven的书
author_obj = models.Author.objects.filter(name='Steven').first()
# 通过作者查书(反向)
res = author_obj.book_set # app01.Book.None
res = author_obj.book_set.all()
print(res)
# 6.查询手机号是100的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=100).first()
res = author_detail_obj.author
print(res.name)
'''
基于对象的反向查询:
当你的查询结果可以是过个的时候,就必须加_set.all()
当你的查询结果只有一个的时候,不需要加_set.all()
'''