ジャンゴ財団のday04は、13になります二重下線間で二重下線クエリ、オブジェクト・テーブル・クエリ全体でCRUDフィールド、クエリのテーブルを知っているだろう



from django.test import TestCase

# Create your tests here.


import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
    import django

    django.setup()
    from app01 import models


    #单表操作13条
    #创建数据的两种方式!!!!!!
    # 1.create方法
    # book_obj=models.Books.objects.create(title='张三丰',price=121.33)
    # print(book_obj)

    #2.利用对象的绑定方法
    # book_obj=models.Books(title='吝啬鬼',price=99)
    # book_obj.save()




    '''
    #查看数据
    # res=models.Books.objects.filter(pk=1)
    # print(res.query)           #<QuerySet [<Books: 张三丰>]>

    pk:
        会自动帮你查找到当前表的主键字段
    所以后期我们都是用pk来指代主键字段。
    filter查询出来的结果是一个Queryset对象:
            <QuerySet [<Books: 张三丰>]>
    1.只要是QuerySet对象,就可以无限制的调用QuerySet的方法【filter()方法等等】
    例如:models.Books.objects.filter(pk=1).filter().filter().filter()
    重复的filter是为了重复的筛选
    2.只要是QuerySet对象,就可以点query查看当前结果内部对应的sql语句
    例如:print(res.query)
    结果:
    SELECT `app01_books`.`id`, `app01_books`.`title`, `app01_books`.`price` FROM `app01_books` WHERE `app01_books`.`id` = 1
    '''




    #修改数据的两种方式
    #方式1,通过.update()方法更新数据
    # 例如要修改id=1的书籍,价格修改为444.66
    # models.Books.objects.filter(pk=1).update(price=444.66)



    #方式2,利用对象来修改数据
    #get方法
    # book_obj=models.Books.objects.get(pk=100)
    # print(book_obj)             #张三丰
    # print(type(book_obj))       #<class 'app01.models.Books'>
    '''
    运行后报错:
    app01.models.DoesNotExist: Books matching query does not exist.
    app01.models。图书匹配查询不存在。
    
    '''


    #对象点属性,再通过对象点save方法修改数据
    #该方法不推荐使用,内部其实是重头到尾把所有字段修改一遍,效率太低
    # book_obj=models.Books.objects.get(pk=1)
    # book_obj.price=888
    # book_obj.save()




    #filter方法推荐使用
    # book_obj = models.Books.objects.filter(pk=100)
    # print(book_obj)  # <QuerySet []>
    # print(type(book_obj))  # <class 'django.db.models.query.QuerySet'>
    '''
    get和filter的区别:
        1.filter获取到的是一个queryset 对象,类似于一个列表
        2.get获取到的直接就是数据对象本身
        当查询条件不存在的情况下:(例如pk=100)
            filter不报错直接返回一个空
            get直接报错,所以不推荐使用get方法
    
    '''



    #删除数据的两种方式
    #1.利用queryset方法   delete() 推荐使用
    # res=models.Books.objects.filter(pk=3).delete()
    # print(res)      #(0, {'app01.Books': 0})


    # 2.对象方法
    # book_obj=models.Books.objects.get(pk=3)
    # book_obj.delete()
    #查询不存在的数据会报错,不推荐使用
    #app01.models.DoesNotExist: Books matching query does not exist.



    #查询数据
    '''
    如果你想查看所有的orm语句对应的sql语句
    你可以在settings配置文件中配置相应的代码即可
    代码如下:
    LOGGING = {
            'version': 1,
            'disable_existing_loggers': False,
            'handlers': {
                'console':{
                    'level':'DEBUG',
                    'class':'logging.StreamHandler',
                },
            },
            'loggers': {
                'django.db.backends': {
                    'handlers': ['console'],
                    'propagate': True,
                    'level':'DEBUG',
                },
            }
        }
    
    '''

    #查询数据   必知必会13条
    #1.all()
    # 查询所有,返回的结果queryset对象
    # res=models.Books.objects.all()
    # print(res)      #<QuerySet [<Books: 张三丰>, <Books: 吝啬鬼>]>
    #orm语句的查询默认都是惰性查询,只有当你真正要使用数据的时候才会执行orm语句




    #2.filter()     在django中推荐使用
    # 筛选,相当于你原生sql语句里面的where关键字,返回的结果queryset对象
    # res=models.Books.objects.filter(pk=1,title='张三丰') #支持多个参数,and关系
    # print(res)      #<QuerySet [<Books: 张三丰>]>




    #3.get()    在django中不推荐使用
    #筛选,获取的是数据对象本身,条件不存在的数据直接报错,并且查询条件必须是唯一的
    # res=models.Books.objects.get(title='西游记')
    # print(type(res))      #报错,因为数据库中没有该数据




    #4.first()
    #取queryset 相同数据中的第一个数据对象
    #id=3,title='西游记'  id=3,title='西游记',优先取id=3的数据
    # res=models.Books.objects.filter(title='西游记').first()
    # print(res)




    # 5.last()
    #取queryset中最后一个数据对象
    # id=3,title='西游记'  id=3,title='西游记',会取出id=4的数据
    # res=models.Books.objects.filter(title='西游记').last()
    # print(res)




    #6.count()
    # 统计数据的个数,结果是一个数字
    # num=models.Books.objects.count()
    # print(num)      #结果为4,代表此时数据库中有四条数据




    #7.values()
    #获取数据对象中指定的字段的值,可以有多个queryset,
    # 列表套字典
    # res=models.Books.objects.values('title','price')
    # print(res)
    #结果:<QuerySet [{'title': '张三丰', 'price': Decimal('888.00')}, {'title': '吝啬鬼', 'price': Decimal('222.00')}, {'title': '西游记', 'price': Decimal('666.00')}, {'title': '西游记1', 'price': Decimal('555.00')}]>




    #8.values_list()
    #获取数据对象中指定的字段的值,可以有多个querylist
    #列表套元组
    # res=models.Books.objects.values_list('title','price')
    # print(res)
    #结果:QuerySet [('张三丰', Decimal('888.00')), ('吝啬鬼', Decimal('222.00')), ('西游记', Decimal('666.00')), ('西游记1', Decimal('555.00'))]>




    #9.order_by()
    #按照指定的字段排序,默认是升序(从小到大)
    # res=models.Books.objects.order_by('price')
    # print(res)
    #结果:<QuerySet [<Books: 吝啬鬼>, <Books: 西游记1>, <Books: 西游记>, <Books: 张三丰>]>

    #降序     是在字段前面加负号(从大到小)
    # res = models.Books.objects.order_by('-price')
    # print(res)
    #结果:<QuerySet [<Books: 张三丰>, <Books: 西游记>, <Books: 西游记1>, <Books: 吝啬鬼>]>




    # 10.reverse()
    # 颠倒顺序,前提是颠倒的对象必须要先排序才能后颠倒
    # res=models.Books.objects.all().order_by('price').reverse()
    # print(res)
    #结果:<QuerySet [<Books: 张三丰>, <Books: 西游记>, <Books: 西游记1>, <Books: 吝啬鬼>]>




    #11.exclude()
    #排除什么什么之外,queryset 对象
    # res=models.Books.objects.all().exclude(title='张三丰')
    # print(res)
    #结果:<QuerySet [<Books: 吝啬鬼>, <Books: 西游记>, <Books: 西游记1>]>




    #12.exists()
    #判断查询结果是否有值,返回结果是一个布尔值
    # res=models.Books.objects.filter(pk=1).exists()
    # print(res)
    #结果:True




    #13.distinct()
    #对查询结果进行去重操作,
    #去重的前提:数据必须是完全相同的情况下,才能够去重复
    #你容易忽略主键,因为主键是不同的,所以我们通过指定的字段来获取数据,然后再进行去重
    # res=models.Books.objects.values('title','price')
    # print(res)
    #结果:<QuerySet [ {'title': '西游记', 'price': Decimal('666.00')}, {'title': '西游记', 'price': Decimal('666.00')}]>

    #去重如下:
    # res=models.Books.objects.values('title','price').distinct()
    # print(res)
    #结果:<QuerySet [ {'title': '西游记', 'price': Decimal('666.00')}]>






    '''***********神奇的双下划线查询******************'''
    #1. __gt   大于
    #查询价格大于500的书籍
    # res=models.Books.objects.filter(price__gt=500)
    # print(res)
    #结果:< QuerySet[ < Books: 张三丰 >, < Books: 西游记 >, < Books: 西游记 >] >



    #2.__lt     小于
    #查询价格小于400的书籍
    # res=models.Books.objects.filter(price__lt=400)
    # print(res)
    #结果:<QuerySet [<Books: 吝啬鬼>]>




    #3. __gte   大于等于
    #查询价格大于等于500的书籍
    # res=models.Books.objects.filter(price__gte=500)
    # print(res)
    #结果:<QuerySet [<Books: 张三丰>, <Books: 西游记>, <Books: 西游记02>]>



    #4. __lte   小于等于
    #查询价格小于等于400的书籍
    # res=models.Books.objects.filter(price__lte=400)
    # print(res)
    #结果:<QuerySet [<Books: 吝啬鬼>]>



    #5. __in    在 什么 里面
    #查询价格是在222,444,500里面的书籍
    # res=models.Books.objects.filter(price__in=[222,444,500])
    # print(res)
    #结果:<QuerySet [<Books: 吝啬鬼>]>




    #6.__range  在什么范围内
    #特点:顾头顾尾
    #查询价格在200 到 800范围内的书籍
    # res=models.Books.objects.filter(price__range=(200,800))
    # print(res)
    #结果:<QuerySet [<Books: 吝啬鬼>, <Books: 西游记>, <Books: 西游记02>]>




    #7. __year   查询年份
    #查询出版日期是2019年的书籍
    # res=models.Books.objects.filter(date__year='2019')
    # print(res)
    # 结果:<QuerySet [<Books: 吝啬鬼>




    #8. __month   查询月份
    #查询出版日期是1月份的书籍
    # res=models.Books.objects.filter(date__month='1')
    # print(res)
    # 结果:<QuerySet [<Books: 吝啬鬼>




    # 9.模糊查询
    '''
    MySQL中的模糊查询
        关键字:like
            模糊匹配的符号:
                    %:匹配任何个数的任意字符
                    _:匹配一位任意的字符
    '''
    #9.1 __startswith   以什么开头
    #查询书籍是以张开头的书
    # res=models.Books.objects.filter(title__startswith='张')
    # print(res)
    #结果:<QuerySet [<Books: 张三丰>]>



    #9.2  __endswith   以什么结尾
    #查询书籍是以丰结尾的书
    # res=models.Books.objects.filter(title__endswith='丰')
    # print(res)
    #结果:<QuerySet [<Books: 张三丰>]>



    #9.3  __contains    包含什么
    #默认区分大小写
    #查询书籍名称中包含p字的书籍
    # res=models.Books.objects.filter(title__contains='三')
    # print(res)
    #结果:<QuerySet [<Books: 张三丰p>]>



    # 9.4  __icontains    包含什么
    # 忽略大小写
    # 查询书籍名称中包含Q字的书籍
    # res=models.Books.objects.filter(title__icontains='Q')
    # print(res)
    # 结果:<QuerySet [<Books: 丰Q了>]>
    
    
    
    
    
    
    
    

#1.django项目的mysql数据库配置
    #第一步.在settings.py文件中配置django项目的数据库为MySQL

DATABASES={
    'default':{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'day53',
        'USER':'root',
        'PASSWORD':'root',
        'PORT':3306,
        'HOST':'127.0.0.1',
        'CHARSET':'utf8'
    }
}
    #第二步:在项目名或者应用名下的__init__.py文件中配置MySQL数据库作为默认数据库
    import pymysql
    pymysql.install_as_MySQLdb()

2.创建数据表在models.py文件中
创建表之后要执行数据库迁移命令,
python manage.py makemigrations,
python manage.py migrate

3.当你想单独测试django中某一个py文件,你需要手动配置测试脚本
    如果没有配置脚本的话,运行代码直接报错
    报错信息:
    django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
    翻译:
    django.core.exceptions。不正确地配置:请求设置DEFAULT_INDEX_TABLESPACE,但是没有配置设置。在访问设置之前,必须定义环境变量DJANGO_SETTINGS_MODULE或调用settings.configure()


'''
正确配置!!!!!!
当你想单独测试django中某一个py文件时,你需要手动配置测试文件
在manage.py文件中拷贝前四行代码,另外再加三行代码
添加:
    import django
    django.setup()
    from app01 import models

'''
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")

    import django
    django.setup()
    from app01 import models    #这一句话只能放在这里,
    因为他必须得等到测试环境搭建好以后才能导入django文件执行测试

单表操作13条
1.create方法



















####################add增、set改、remove移除、clear清空四个方法的使用###################

# 一对多字段数据的增删改查

    # 增
    # models.Book.objects.create(title='三国演义',price=222.33,publish_id=1)
    '''
    方法:
        第一种.传实际字段,利用publish_id=1,直接传表里面的实际字段,对应更新到数据库中
        第二种.虚拟字段传数据对象,通过虚拟字段,利用对象来创建

    '''
    # publish_obj=models.Publish.objects.filter(pk=2).first()
    # models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj)

    # 查

    # 改
    # 第一种    传实际字段
    # models.Book.objects.filter(pk=1).update(publish_id=2)
    # django中默认id作为主键,此处代表查询主键id=1的数据,pk=1 等同于 id=1
    # update(表中字段A = 字段值B)

    # 第二种    虚拟字段传数据对象
    # publish_obj=models.Publish.objects.filter(pk=1).first()
    # models.Book.objects.filter(pk=1).update(publish=publish_obj)

    # 删  (知道即可,工作中不要使用)
    # 默认的是级联删除、级联更新
    # models.Publish.objects.filter(pk=3).delete()

# 多对多字段数据的增删改查

# 增(add)
#     方法一:(传数字)
#     方法二:(传对象)


    # book_obj=models.Book.objects.filter(pk=2).first()
    # 给当前这一本书绑定作者
    # 1.手动添加---绝对不推荐
    # 2.通过对象点属性【自我理解为:对象点虚拟字段-->直接进入第三张表】-->跨到第三张表
    # print(book_obj.publish)       #北方出版社
    # print(book_obj.authors)     #app01.Author.None
    # book_obj.authors.add(1)     #在第三张表里面给书籍id=2的添加一个author_id=1 的作者

    # 【自我理解为:对象点虚拟字段-->是直接进入第三张表】
    '''
    结果就是:
    id  book_id  author_id
     1      2       1
    '''
    # book_obj.authors.add(1,2)   #在第三张表里面给书籍id=2的添加两个作者,
    # 一个是author_id=1的作者,另一个是author_id=2的作者

    '''
   结果就是:
   id  book_id  author_id
    1      2       1
    2      2       2
    '''
    # book_obj = models.Book.objects.filter(pk=2).first()
    # author_obj=models.Author.objects.filter(pk=1).first()
    # author_obj1=models.Author.objects.filter(pk=2).first()
    # # book_obj.authors.add(author_obj)
    # book_obj.authors.add(author_obj,author_obj1)

    '''
    方法一:(传数字)
        add方法   能够朝第三张关系表添加数据
            即支持传数字
                add(1,2)

            也支持传对象
                add(author_obj,author_obj100)

            并且无论是传数字还是传对象都是可以传多个值


    '''

    '''
方法二:(传对象)
    book_obj = models.Book.objects.filter(pk=2).first()
    author_obj=models.Author.objects.filter(pk=1).first()
    book_obj.authors.add(author_obj)

    # 【第三句自我理解为:对象点虚拟字段-->是直接进入到第三张表关系表】
        book_obj.authors.add(author_obj)

    这里面是通过book_obj对象点Book表中的虚拟字段authors,直接进入到
    第三张书籍与作者的book_authors关系表,然后添加了Author作者表
    pk为1的对象

        对于Book表中虚拟字段authors最通俗的介绍就是:牵线红娘
    帅哥          通过红娘(authors)           美女
    单身        ------------------------>      漂亮

单身帅哥book_obj通过通过红娘(authors添加了(add)漂亮美女,组成了一个家庭。
结果就是:
   id  book_id  author_id
    1      2       1


    '''

# 改(set,注意set(这里还有一个括号()))
    #方法一:传数字
    #方法二:(传对象)

# 方法一:传数字
#     book_obj=models.Book.objects.filter(pk=2).first()
#             book_obj.authors.set((1,3))
'''
TypeError: set() takes 2 positional arguments but 3 were given
set()必须是一个可以迭代的对象,可以迭代的对象有:元祖、列表、字典、集合、字符串
使用set其实是先在数据库中删除对应的数据,然后再增加对应的数据
set()----set里面必须得传一个可以迭代的对象,不然会报错,
例如:book_obj.authors.set(1)
TypeError:'int' object is not iterable
整形不是可以迭代的对象

book_obj=models.Book.objects.filter(pk=2).first()
book_obj.authors.set('33')
如果set字符串33的话,
表中的数据只有一个结果,就是除了author_id=3的,
别的(author_id=1和author_id=2)都没了,
结果就是:
   id  book_id  author_id
    1      2       3
**********************************************************
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.set((1, 3))
# 在第三张表里面给书籍book_id=2的字段【重新设置】两个作者id,
# 一个是author_id=1的作者,另一个是author_id=2的作者

# 该方法有漏洞,如果book_id=2对应的作者id有5个,那么set((1,3)),
# 就会出问题了,一旦执行代码,
就会把book_id=2对应的author_id=2和author_id=4,和author_id=5的数据删除掉


'''
# book_obj = models.Book.objects.filter(pk=2).first()
# book_obj.authors.set((1, 3))

# 方法二:(传对象)
#     book_obj=models.Book.objects.filter(pk=2).first()
#
#     author_obj01=models.Author.objects.filter(pk=1).first()
#     author_obj02=models.Author.objects.filter(pk=2).first()
#     book_obj.authors.set((author_obj01,author_obj02))
#
'''
set修改多对多关系表中的数据
    既可以传数字也可以传对象
    但是需要注意的是括号内必须是可迭代对象
    同样都支持多个数字和对象
        set((1,3))
        set((author_obj,author_obj02))

'''


#删除
#移除一个
#在book_authors表中移除author_id=1的数据
# book_obj=models.Book.objects.filter(pk=2).first()
# book_obj.authors.remove(1)
'''
结果就是:
   id  book_id  author_id
    1      2       2

'''
#移除多个
# book_obj=models.Book.objects.filter(pk=2).first()
# book_obj.authors.remove(1,2)

'''
结果就是:
   id  book_id  author_id
    1      2       3

'''
#传单个对象
# book_obj=models.Book.objects.filter(pk=2).first()

# author_obj01=models.Author.objects.filter(pk=1).first()
# author_obj02=models.Author.objects.filter(pk=2).first()

# book_obj.authors.remove(author_obj01)
#传多个对象
# book_obj.authors.remove(author_obj01,author_obj02)
'''
remove 既可以传数字,也可以传对象
    并且都支持传多个值,不需要迭代
        remove(1,2)
        remove(author_obj01,author_02)

'''

#清空表数据       删除某个数据在第三张表中的所有记录
# book_obj=models.Book.objects.filter(pk=2).first()
# book_obj.authors.clear()
'''
clear 清空书籍相关所有记录,括号内不需要传任何参数。
'''

############################ 跨表查询##############################
#------------------情况01.基于对象的跨表查询----对应MySQL中的子查询,【子查询,分步操作】

# 什么是子查询,就是将一张表的查询结果,作为另一张表的查询条件
'''
正反向查询:
    A表(有外键关联到B表)       B表
    关系字段在谁哪?由谁查谁就是正向,
    关系字段在A那,由A查B是正向----称之为正向查询
                   由B查A是反向-----称之为反向查询

    正向查询按字段
    反向查询按表名小写_set

'''
#1.查询书籍主键为2的出版社名称
#    书查出版社是正向查询,按字段
# book_obj=models.Book.objects.filter(pk=2).first()
# print(book_obj.publish)         #    出版社对象
# print(book_obj.publish.name)    #    打印结果:北方出版社

#2.查询书籍主键为4的作者姓名
#    书查作者是正向查询,按字段
# book_obj=models.Book.objects.filter(pk=4).first()
# print(book_obj.authors)     #标志性结果app01.Author.None,不代表代码错误,仅仅是少了一个 .all()
# print(book_obj.authors.all())   #<QuerySet [<Author: oscar>, <Author: egon>]>

#3.查询作者是jason的手机号码
# #这个是问题代码,原因是由于在models中的Author表建立表与表关系的时候,写错了一个单词
# author_obj=models.Author.objects.filter(name='jason').first()
# res = models.Author.objects.filter(name='jason')
# print(author_obj)
# print(author_obj.author_detail.phone)       #结果:110

'''
什么时候需要加all
当正向查询点击外键字段数据有多个的情况下,需要 .all()比如,一本书多个作者
当反向查询点击表名小写_set之后有多个值的情况下,需要 .all() 查询所有
标志性结果app01.Author.None  一旦看到该结果,只需要加.all()即可


在写orm语句的时候,跟你写sql语句一样,不要想着一次性写完,
写一点差一点再写一点


'''

#4.查询出版社是东方出版社出版过的书籍,并且打印书籍的名称
#  通过出版社查书籍是反向查询,反向查询表名小写_set
# publish_obj=models.Publish.objects.filter(name='东方出版社').first()
# print(publish_obj.book_set)             #app01.Book.None
# print(publish_obj.book_set.all())       #<QuerySet [<Book: Book object>, <Book: Book object>]>
# book=publish_obj.book_set.all()         #<QuerySet [<Book: Book object>, <Book: Book object>]>
#QuerySet,用for循环取列表中的对象,通过print(对象.属性),获取对应的值
# for i in book:
#     print(i.title)      #三国演义、水浒传

#5.查询作者是jason写过的书籍
#   通过作者查书籍是反向查询,反向查询表名小写_set
# author_obj=models.Author.objects.filter(name='jason').first()
# print(author_obj.book_set)          #app01.Book.None
# print(author_obj.book_set.all())    #<QuerySet [<Book: Book object>, <Book: Book object>]>

#6.查询手机号是120的作者姓名
#作者详情查作者,反向查询,表名小写_set
# author_detail_obj=models.AuthorDetail.objects.filter(phone=120).first()
# print(author_detail_obj.author)
# print(author_detail_obj.author.email)   #[email protected]
# print(author_detail_obj.author.name)    #oscar
'''
反向查询 :
什么时候表名加  _set,总结:
    当你反向查询的数据是多个的时候就需要表名加上  _set,
    当你反向查询的数据是一个的时候就不需要加  _set

专业总结术语如下:

    查询的表关系中外键上书写的是 一对多、多对多的情况需要加  _set
    查询的表关系中外键上书写的是一对一,这种情况不需要加  _set

    一对多:ForeignKey      (django中没有OneToManyField)
    多对多:ManyToManyField
    一对一:OneToOneField

'''


#---------------------情况02.基于双下划线的跨表查询      联表操作
'''
inner join
left join
right join
union

'''

#***************双下划线的跨表查询**************重点中的重点优先掌握************************
'''
values方法总结:
values('publish__name')
values中写外键字段就相当于已经跨到了外键字段所关联的表
你想要该表中的哪个字段,只需要双下字段名(__name)获取即可
'''

#1.查询书籍pk为2的出版社名称
#       正向
# res=models.Book.objects.filter(pk=2).values('publish__name')
# values中publish一写,就代表已经跳转到了Publish这张表,然后双下name来取字段的值
#需要注意的是values里面有引号,自己总是忘记写
# print(res)        #<QuerySet [{'publish__name': '北方出版社'}]>

'''         filter()括号里面既支持正向,同时也支持反向   '''
#       反向
# print(models.Publish.objects.filter(book__pk=2))    #<QuerySet [<Publish: 北方出版社>]>
# res=models.Publish.objects.filter(book__pk=2).values('name')
# print(res)      #<QuerySet [{'name': '北方出版社'}]>


#2.查询书籍pk为2的作者姓名
#           正向
# res=models.Book.objects.filter(pk=2).values('authors__name')
# print(res)    #<QuerySet [{'authors__name': 'jason'}, {'authors__name': 'oscar'}]>
#   查询书籍pk为2的作者姓名和邮箱
# res=models.Book.objects.filter(pk=2).values('authors__name','authors__email')
# print(res)
#打印结果<QuerySet [{'authors__name': 'jason', 'authors__email': '[email protected]'}, {'authors__name': 'oscar', 'authors__email': '[email protected]'}]>

#           反向
# res=models.Author.objects.filter(book__pk=2).values('name')
# print(res)       #<QuerySet [{'name': 'jason'}, {'name': 'oscar'}]>
#
# res=models.Author.objects.filter(book__pk=2).values('name','email')
# print(res)
#打印结果<QuerySet [{'name': 'jason', 'email': '[email protected]'}, {'name': 'oscar', 'email': '[email protected]'}]>


#3.查询作者是egon的家庭地址
#               正向
# res=models.Author.objects.filter(name='egon').values('author_detail__addr')
# print(res)      #<QuerySet [{'author_detail__addr': '山东'}]>

#               反向
# res=models.AuthorDetail.objects.filter(author__name='egon').values('addr')
# print(res)          #<QuerySet [{'addr': '山东'}]>


#4.查询出版社是东方出版社出版过的书的名字
#               正向
# res=models.Publish.objects.filter(name='东方出版社').values('book__title')
# print(res)      #<QuerySet [{'book__title': '三国演义'}, {'book__title': '水浒传'}]>

#               反向
# res=models.Book.objects.filter(publish__name='东方出版社').values('title')
# print(res)      #<QuerySet [{'title': '三国演义'}, {'title': '水浒传'}]>


#最复杂之orm查询,查询书籍pk=2的作者的手机号
#               正向
# res=models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
# print(res)  #<QuerySet [{'authors__author_detail__phone': 110}, {'authors__author_detail__phone': 120}]>

#               反向
# res=models.Author.objects.filter(book__pk=2).values('author_detail__phone')
# print(res)
#打印结果:<QuerySet [{'author_detail__phone': 110}, {'author_detail__phone': 120}]>






おすすめ

転載: www.cnblogs.com/ludundun/p/11963767.html