Django:模型_ORM查询条件_补充

基于双下划线的跨表查询

1、Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认SQL JOIN联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的model为止

2、基于双下划线的跨表查询,其本质是使用join连接其他表进行查询(连表查询)

3、基于双下划线的跨表查询:如果为正向查询(子表查询主表)则按字段,反向查询时则按表名小写

 

一对多

⑴编辑模型:Book模型中用于连接Author表的外键名实际为"author_a"这张图在截图后修改过一下,为了方便区分主表模型名小写形式(author)和Book模型中的外键属性名(author->author_a)


⑵查看数据


例1:查询作者是"吴承恩"的所有图书

# -*- coding: utf-8 -*-
from django.http import HttpResponse
from polls.models import Author,Book,Publisher,BookOrder
from django.db import models
from django.db import connection

def index(request):
    #查询作者是"吴承恩"的所有图书

    #正向查询:外键字段__关联表的字段
    result = Book.objects.filter(author_a__name='吴承恩')#这个例子中专门把外键属性名定义来跟主表的模型名不一致,以便区分
    print(result)
    print(result.query)
    
    #反向查询:表名__字段
    result_1 = Author.objects.filter(name='吴承恩').values("book","book__name")
    print(result_1)
    print(result_1.query)

    result_2 = Author.objects.filter(name='吴承恩').values("book")
    print(result_2)
    print(result_2.query)
    return HttpResponse("success")

"""
<QuerySet [<Book: Book object (1)>, <Book: Book object (3)>]>
SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_a_id`, `book`.`publisher_a_id`, 
`book`.`create_time`, `book`.`update_time` FROM `book` INNER JOIN `author` ON (`book`.`author_a_id` = `author`.`id`) WHERE `author`.`name` = 吴承恩

<QuerySet [{'book__name': '西游记', 'book': 1}, {'book__name': '西游记后传', 'book': 3}]>
SELECT `book`.`id`, `book`.`name` FROM `author` LEFT OUTER JOIN `book` 
ON (`author`.`id` = `book`.`author_a_id`) WHERE `author`.`name` = 吴承恩

<QuerySet [{'book': 1}, {'book': 3}]>
SELECT `book`.`id` FROM `author` LEFT OUTER JOIN `book` 
ON (`author`.`id` = `book`.`author_a_id`) WHERE `author`.`name` = 吴承恩
"""


例2:查询"西游记"这本书的作者

# -*- coding: utf-8 -*-
from django.http import HttpResponse
from polls.models import Author,Book,Publisher,BookOrder
from django.db import models
from django.db import connection

def index(request):
    #查询"西游记"这本书的作者

    #正向查询:外键字段__关联表的字段
    result = Book.objects.filter(name="西游记").values("author_a__name")
    print(result)
    print(result.query)

    #反向查询:表名__字段
    result_1 = Author.objects.filter(book__name='西游记')
    print(result_1)
    print(result_1.query)
    return HttpResponse("success")

"""
<QuerySet [{'author_a__name': '吴承恩'}]>
SELECT `author`.`name` FROM `book` INNER JOIN `author` 
ON (`book`.`author_a_id` = `author`.`id`) WHERE `book`.`name` = 西游记

<QuerySet [<Author: Author object (1)>]>
SELECT `author`.`id`, `author`.`name`, `author`.`age`, `author`.`email` 
FROM `author` INNER JOIN `book` ON (`author`.`id` = `book`.`author_a_id`) WHERE `book`.`name` = 西游记
"""

注:从上面两个例子可以看出,在进行查询时
1、首先要分清楚最终要查询的数据是在子表中还是主表中
    ⑴查询作者是"吴承恩"的所有图书:最终查询的是"图书",因此是在子表中(Book模型类中)
    ⑵查询"西游记"这本书的作者:最终查询的是"作者",因此是在主表中(Author模型类中)

2、确定好查询语句是从哪个表查询到哪个表(主表和子表)
    ⑴查询作者是"吴承恩"的所有图书(最终查询的语句是在子表中),且查询语句以"Book"模型类开始,那么为"正向查询",方法为:外键字段__关联表的字段 (关联表的字段是可变的:即,需要根据哪个字段来查询就是哪个字段,author_a__name中就是根据主表中的name来查询的)
    ⑵查询作者是"吴承恩"的所有图书(最终查询的语句是在子表中),且查询语句以"Author"模型类开始,那么为"反向查询",方法为:表名__关联表的字段 (关联表的字段是可变的)

2.1、确定好查询语句是从哪个表查询到哪个表(主表和子表)
    ⑴查询"西游记"这本书的作者(最终查询的语句是在主表中),且查询语句以"Book"模型类开始,那么为"正向查询",方法为:外键字段__关联表的字段
    ⑵查询"西游记"这本书的作者(最终查询的语句是在主表中),且查询语句以"Author"模型类开始,那么为"反向查询",方法为:表名__关联表的字段


3、可以看出:
    ⑴如果最终查询的数据在子表中:那么最好以"子表模型类"开始:使用正向查询,外键字段__关联表的字段
    ⑵如果最终查询的数据在主表中:那么最好以"主表模型类"开始:使用反向查询,表名__字段

4、values()方法中的第一个参数可以要可以不要:
    ⑴不要,即直接为values("表名__需要查询的字段名"):这样查询结果就是一个字典型的集合(键为表名,值为数据id值)
    ⑵要,即为values("表名__需要查询的字段名"):这样查询出来的就是将需要查询的字段的值赋值给"表名__需要查询的字段名"的变量,将数据id值赋值给第一个参数变量(感觉最好还是要有第一个参数比较好些,可以使用表名来作为第一个参数)
 

 

 

基于对象的跨表查询

1、关系属性(字段)写在哪个类(表) 里面,从当前类(表)的数据去查询它关联类(表)的数据叫做正向查询,反之叫做反向查询

2、基于对象的查询是子查询,也就是多次查询
    ⑴正向查询:正向查询靠对象,取到数据对象后,通过点操作符对外键操作,就能拿到外键的对象,从而取到内容
    ⑵反向查询:查到对象后,通过小写的表名_set来获取另一个表的属性(注意对象调用的是加_set 的方法,然后all()即可取出全部内容)

3、基于对象查询的特点在于:不管是正向查询还是反向查询,第一步查询出来的数据都只能有一条(使用get()或first()等)
    ⑴正向查询:先查询子表,子表的查询结果只能有一条(主表的数据视表关系而决定)
    ⑵反向查询:先查询主表,主表的查询结果也只能有一条,子表对应的数据可以有一条或多条,使用all()方法获取全部子表数据

4、基于双下划线的跨表查询的特点在于:子表和主表查询出来的结果都可以是多条(视具体的表关系而定)

5、使用"模型类.字段名"来获取某一个列具体的值时:
    ⑴前提是返回的是一个模型类,而不是一个QuerySet对象。如果是一个QuerySet对象,那么就需要通过for循环遍历来依次返回每个具体数据的模型类
    ⑵只有返回数据是一条数据的模型类时,才能使用"模型类.字段名"来获取某一个列具体的值:如一对多中,子表到主表,主表肯定只有一条数据,那么就可以直接使用"模型类.字段名"来获取某一个列具体的值
    ⑶如果返回的是多条数据的模型类,那么就必须先使用for循环来遍历依次得到每条数据的模型类,然后才能使用"模型类.字段名"来获取某一个列具体的值:如一对多中,主表到子表,子表数据可以有一条或多条,当为多条时先使用all()来获取全部数据(此时为一个QuerySet对象),然后遍历,再使用"模型类.字段名"

例3:

# -*- coding: utf-8 -*-
from django.http import HttpResponse
from polls.models import Author,Book,Publisher,BookOrder
from django.db import models
from django.db import connection

def index(request):
    #查询"西游记"这本书的作者
    #正向查询:按字段
    result = Book.objects.filter(name="西游记").first()#如果不使用first()方法,则返回的是一个QuerySet对象,如果是一个QuerySet对象,那么就不能使用实例名.属性名
    print(result.author_a)
    print(type(result.author_a))#结果为一个模型类,不能使用.query方法

    # 查询作者为"吴承恩"的图书
    #反向查询:按表名小写_set.all()
    result_1 = Author.objects.filter(name='吴承恩').first()#如果不使用first()方法,则返回的是一个QuerySet对象,如果是一个QuerySet对象,那么就不能使用小写子表模型名_set属性
    book_1 = result_1.book_set.all()#子表中存在多条数据,使用all()方法获取全部数据
    print(book_1)
    return HttpResponse("success")

"""
Author object (1)
<class 'polls.models.Author'>

<QuerySet [<Book: Book object (1)>, <Book: Book object (3)>]>
"""

注:
一对一、一对多、多对多表关系的"基于对象的跨表查询"的查询方式,可以参照"表关系"那节

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值