ORM--基于双下划线的跨表查询


1.基于双下划线的跨表查询

表模型请参考多表操作
数据准备以及路径配置等等请参考 基于对象的跨表查询
其他配置请参考前面几小节的博客

app01/views.py

from django.shortcuts import render,HttpResponse
from app01.models import *
def query(request):
    """跨表查询
        1 基于对象查询
        2 基于双下划线查询
        3 聚合和分组查询
        4 F 与 Q 查询
    """
    # ===============  基于双下划线的跨表查询 (join查询)============
    #     正向查询按字段,反向查询按照表名小写 告诉ORM引擎join那张表
    # =====一对多查询
    # 的正向查询:查询Python这本书的出版社的名字
    """原生SQL
    select app01_publish.name from app01_book inner join app01_publish
    on app01_book.publish_id = app01_publish.nid
    where app01_book.title = "Python";
    """
    # ORM实现方式,随便一张表作为基表都可以

    # 方式一:正向查询按字段 .values('字段__查询的名字') 这里的values() 相当join
    # (这个字段是指 关联外键的字段<<指代关联的表的记录对象,后面没有加_id的那个!>>)
    ret = Book.objects.filter(title='Python').values('publish__name')
    print(ret)

    # 方式二:反向查询关联的表的表名小写 .过滤条件例如filter(表名小写__字段... = 条件) 这里的filter()相当于join
    res = Publish.objects.filter(book__title='Python').values("name")
    print(res)

    # 方式一和方式二翻译成的SQL语句差不多一样(inner join 左右边的顺序交换了,效果是一样的)

    # =====多对多的查询
    # 查询Python这本书的所有的作者的名字
    """原生SQL
    select app01_author.name from app01_book 
    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_book.title = "Python";
    """
    # 方式一,正向 通过Book表内的字段<<关联记录对象authors>>join其关联的Author表,
    ret = Book.objects.filter(title="Python").values("authors__name")
    print(ret)

    # 方式二、反向 注意!是两个杠 __
    res = Author.objects.filter(book__title="Python").values('name')
    print(res)

    # ===== 一对一的查询 查询egon的手机号
    # 方式一:正向 注意!values 只能被QuerySet调用
    ret = Author.objects.filter(name='egon').values("authordetail__telephone")
    print(ret)

    # 方式二:反向
    res = AuthorDetail.objects.filter(author__name='egon').values('telephone')
    print(res)


    # ================ 进阶练习 (根据Pycharm提示和自己的见解领悟出来的)========
    # ===== 连续跨表查询 比如 A与B关联  B与C关联  A与C没有直接关联,要求通过A查询C里面的信息
    """
    自己总结:1.以基表为准(写在.objects之前的),通过filter等或者values等调用被关联对象字段<<记录对象>>或者关联的表名小写,
            根据需要以递归的方式重复以上调用,最后调用相关的字段属性和条件。
            
            2.总之,就是以基表为准通过双下划线__根据被关联(调字段)或者关联(调表表名小写)和字段、条件进行链式调用!
            
            3.记住两个关键点:正向查按照被关联表字段!
                           反向查按关联表的表名小写!
                           
            4.这东西很活,根据以上的规则什么问题都解决了!
    """
    # 查询成都中医药大学出版社出版过的所有书籍的作者姓名及书籍的名字
    # Author  多<--->多   Book  多<--->一   Publish
    # 正向查询
    res = Book.objects.filter(publish__name='成都中医药大学出版社').values("title","authors__name")
    print(res)

    # 反向查询1
    res = Publish.objects.filter(name='成都中医药大学出版社').values("book__authors__name",'book__title')
    print(res)

    # 反向查询2 查询成都中医药大学出版社出版过的所有书籍的作者姓名及书籍的名字
    ret = Author.objects.filter(book__publish__name="成都中医药大学出版社").values('name','book__title')
    print(ret)

    # 手机号以181开头的作者出版过的所有 书籍名称 以及 出版社名称
    #  AuthorDetail  一<--->一   Author  多<--->多   Book  多<--->多   Publish
    # 正向查询 regex是正则的意思
    res = Book.objects.filter(authors__authordetail__telephone__regex="181").values("title","publish__name")
    print(res)

    # 综合查询?
    res = Author.objects.filter(authordetail__telephone__startswith="181").values("book__title","book__publish__name")
    print(res)

    
    return HttpResponse("OK")
    
posted @ 2018-07-21 19:29  哈哈大圣  阅读(243)  评论(0编辑  收藏  举报