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')
    # 只影响反向查询
    # 基于对象和基于双下划线的查询都受影响

posted @ 2020-08-05 16:16  straightup  阅读(100)  评论(0编辑  收藏  举报