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) #444@qq.com
# 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': '123@qq.com'}, {'authors__name': 'oscar', 'authors__email': '444@qq.com'}]>
# 反向
# 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': '123@qq.com'}, {'name': 'oscar', 'email': '444@qq.com'}]>
#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}]>