Django学习6
查询
基于对象的跨表查询 --- 类似于子查询
正向查询和反向查询
从有关系属性(字段)的表(类)出发去查它关联的表(类)为正向, 反之反向
一对一
# 正向查询(查崔老师的电话)
author_obj = models.Author.objects.filter(name='崔老师').first() # 找到崔老师这个对象
print(author_obj.authorDetail.telephone) # 13838383838
# 反向查询(已知电话13838383838,查主人)
author_detail_obj = models.AuthorDetail.objects.get(telephone='13838383838') # 找到电话对象
print(author_detail_obj.author.name) # 崔老师 对象.小写的表名 --> 拿到崔老师这个对象
'''
正向查询:author_obj.authorDetail, 对象.关联属性名
Author -------------------------------> AuthorDetail
<-------------------------------
反向查询:author_detail_obj.author, 对象.小写关联类名
'''
一对多
# 正向查询(知道书籍名称查出版社)
book_obj = models.Book.objects.get(title='李帅的床头故事')
print(book_obj.publishs.name) # 哥哥出版社
# 反向查询(知道出版社名称想查它出了哪些书)
publish_obj = models.Publish.objects.get(name='哥哥出版社')
print(publish_obj.book_set.all()) # <QuerySet [<Book: b哥的往事>, <Book: 李帅的床头故事>, <Book: 李帅的床头故事2>]>
'''
正向查询:book_obj.publishs, 对象.关联属性名
Book -------------------------------------> Publish
<-------------------------------------
反向查询:publish_obj.book_set.all(), 对象.小写类名_set.all()
'''
多对多
# 正向查询(知道书名找作者)
book_obj = models.Book.objects.get(title='李帅的床头故事')
print(book_obj.authors.all()) # <QuerySet [<Author: 高杰>, <Author: 文洋>]>
# 反向查询(知道作者找他写的书)
author_obj = models.Author.objects.get(name='高杰')
print(author_obj.book_set.all()) # <QuerySet [<Book: 李帅的床头故事>, <Book: b哥的往事>]>
'''
正向查询:book_obj.authors.all(), 对象.关联属性名.all()
Book -------------------------------------> Author
<-------------------------------------
反向查询:author_obj.book_set.all(), 对象.小写类名_set.all()
'''
基于双下划綫的跨表查询 --- 连表 join
一对一
# 1.查崔老师的电话号码
# 方式一 (正向 作者表在前)
models.Author.objects.filter(name='崔老师').values('authorDetail__telephone')
# 方式二 (反向 作者信息表在前)
models.AuthorDetail.objects.filter(author__name='崔老师').values('telephone','author__age')
# 2.查询电话为13838383838的老师
# 方式一 (正向)
models.Author.objects.filter(authorDetail__telephone='13838383838').values('name','authorDetail__addr')
# 方式二 (反向)
models.AuthorDetail.objects.filter(telephone='13838383838').values('author__name')
一对多
# 1.查询一下<李帅的床头故事>这本书的出版社
# 方式一 (正向)
models.Book.objects.filter(title='李帅的床头故事').values('publishs__name')
# 方式二 (反向)
models.Publish.objects.filter(book__title='李帅的床头故事').values('name')
# 2.哥哥出版社出版了哪些书
# 方式一 (正向)
models.Book.objects.filter(publishs__name='哥哥出版社').values('title')
# 方式二 (反向)
models.Publish.objects.filter(name='哥哥出版社').values('book__title')
多对多
# 1.<李帅的床头故事>是谁写的
# 方式一 (正向)
models.Book.objects.filter(title='李帅的床头故事').values('authors__name')
# 方式二 (反向)
models.Author.objects.filter(book__title='李帅的床头故事').values('name')
# 2.高杰写了哪些书
# 方式一 (正向)
models.Book.objects.filter(authors__name='高杰').values('title')
# 方式二 (反向)
models.Author.objects.filter(name='高杰').values('book__title')
进阶
# 1.哥哥出版社出版的书的名称以及作者的名字(三张表)
# 方式一
models.Publish.objects.filter(name='哥哥出版社').values('book__title','book__authors__name')
# 方式二
models.Book.objects.filter(publishs__name='哥哥出版社').values('title','authors__name')
# 方式三
models.Author.objects.filter(book__publishs__name='哥哥出版社').values('book__title','name')
# 2.手机号以139开头的作者出版过的所有书籍名称以及出版社名称
# 方式一
models.AuthorDetail.objects.filter(telephone__startswith='138').values('author__book__title','author__book__publishs__name')
# 方式二
models.Author.objects.filter(authorDetail__telephone__startswith='138').values('book__title','book__publishs__name')
# 聚合
from django.db.models import Avg,Max,Min,Sum,Count
# 计算所有图书的平均价格
obj = models.Book.objects.all().aggregate(Avg('price'))
# obj = models.Book.objects.all().aggregate(avg_price=Avg('price')) 可命名
print(obj) # {'price__avg': 2.833333} 返回的是字典!
# 其余写法类似
小结:
# 1.无论是基于对象还是基于双下划綫,正向查询就是属性名称,反向查询就是表名小写
# 2.其中基于对象,反向查询多个结果要加_set,而在基于双下划綫没有_set一说
# 3.基于双下划綫,正向连表:属性名称__ ; 反向连表:表名小写__
零碎知识点
1.打印翻译过来的sql语句,在settings.py中配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
2.建表时外键定制related_name,反向查询的时候用related_name代替小写表名
authors=models.ManyToManyField(to='Author',related_name='xx')
# 只影响反向查询
# 基于对象和基于双下划线的查询都受影响