day08 外键字段的增删改查 正向反向插叙概念 跨表查询 聚合查询与分组查询 F查询
昨日内容复习
-
自定义过滤器、标签、inclusion_tag
1.首先现在应用目录下创建名字为templatetags的文件夹 2.文件夹里创建任意名称的.py文件 里面写两行内容 from django import template register=template.library() @register.filter() 过滤器 @register.simple_tag() 标签 @register.inclusion_tag() inclusion_tag html页面使用需要先加载 {%load py文件名 %}
-
模板的继承和导入
先在母版中利用block划定将来可以被修改的区域 {% block 区域名称 %} 母版内容 {% endblock %} 在子版中先继承 {% extends 母版名 %} {% block 区域名称 %} 子版内容 {% endblock %} """ 在母版中至少应该含有三块区域 css、content、js 在子版中也可以继续使用母版的内容 {{ block.super }} """ ######################### 模板的导入其实就是将页面的某个部分当做组件的形式 导入到其他页面的某个位置上(使用频率不高) {% include 文件名称 %} 如何创建django测试文件 方式1:使用pycharm自动提供的python console 方式2:拷贝manage.py前四行内容 再加上固定的两句(任意文件) import django django.setup() 如何查看orm内部的SQL语句 方式1:针对结果为queryset对象可以直接点query查看 方式2:直接在配置文件中拷贝固定的代码即可 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
-
查询关键字
""" pk特指主键 自动查找主键名称 """ all() # 查询所有 filter() # 类似于where筛选 括号内逗号隔开多个条件默认是and关系 get() # 查找具体的数据对象 条件不存在直接报错(不推荐使用) values() # 结果相当于列表套字典(指定查询的字段) values_list() # 结果相当于列表套元组(指定查询的字段) first()、last() # 拿queryset数据集中第一个和最后一个数据 order_by() # 排序 distinct() # 去重(有主键的情况下肯定无法去重) exclude() # 取反 exists() # 判断是否有结果 返回True或False
-
神奇的双下划线
字段名__gt=值 某个字段大于某个值的数据对象 字段名__gte=值 某个字段大于等于某个值的数据对象 字段名__lt=值 某个字段小于某个值的数据对象 字段名__lte=值 某个字段小于等于某个值的数据对象 字段名__in=['123','234'] 某个字段等于值1或值2或值3 的数据对象 加引号看前提 ,如果是浮点型要加引号,因为python对浮点数这块不够精确 字段名__range=(200,500) 某个字段的值在200-500之间 的数据对象 字段名__contains='p' 某个字段的值包含字母'p'之间 的数据对象 区分大小写 字段名__icontains='p' 某个字段的值包含字母'p'之间 的数据对象 不区分大小写 字段名__startswith='人' 某个字段以'人'开头的数据对象 字段名__ebdswith='的' 某个字段以'的'结束的数据对象 #前提是日期类型 字段名__year=2021 某个字段的年份为'2021'的数据对象 字段名__month=11 某个字段的月为'11'的数据对象
-
多表查询数据准备
针对一对多和一对一 orm都会给字段名称后面自动加_id后缀(不要自己加) 针对多对多字段 无需我们自己创建第三张表 写在关系表中 自动创建
-
今日内容概要
- 外键字段的增删改查
- 正反向查询的概念
- 基于对象的跨表查询(子查询)
- 基于双下划綫的跨表查询(连表操作)
- 聚合查询与分组查询
- F查询与Q查询
今日内容详细
-
外键字段的增删改查
#一对一 一对多 #增 #直接录入数据 # models.Book.objects.create(title='活着',price=256.32,publish_id=1) #创建出版社对象录入数据 first 获取第一个数据 不加则是 一个列表套数据对象 加获取第一个位置的数据对象 #publish可以传数据对象 # publish_obj=models.Publish.objects.filter(pk=2).first() # models.Book.objects.create(title='三国义',price=123.52,publish=publish_obj) #改 #直接修改 # models.Book.objects.filter(pk=2).update(publish_id=1) #传入数据对象修改 先创建出版社对象 通过publis指定数据对象 # publish_obj=models.Publish.objects.filter(pk=2).first() # models.Book.objects.filter(pk=1).update(publish=publish_obj) #删查 soeasy #多对多操作 #增 add # 获取一个book对象 # book_obj=models.Book.objects.filter(pk=3).first() # book_obj.authors.add(1) #操作虚拟字段相当于操作第三张表add(添加对方的id,可以写多个,因为是多对多) # book_obj.authors.add(1,2) #创建book对象 作者对象 通过book.虚拟字段.add(作者对象1,作者对象2)添加关系 # book_obj = models.Book.objects.filter(pk=3).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,author_obj1) """ add 在第三张关系表中添加数据 括号内既可以传主键字段也可以传数据对象 并且都支持传多个 """ #改 set # book_obj=models.Book.objects.filter(pk=2).first() # 报错'int' object is not iterable int对象不可迭代,可以换一个可迭代对象试一下 元组列表字典 # book_obj.authors.set(2) #记住指定的是虚拟字段 谁创建的谁调用 # book_obj.authors.set([2]) #可以指定多个set([2,1]) 因为是多对多 #修改也可以用对象修改 # 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.set([author_obj]) # book_obj.authors.set([author_obj,author_obj1]) """ set 在第三张关系表中修改数据 括号内需要传一个可迭代对象 可迭代对象里面的元素既可以传主键字段也可以传数据对象 并且都支持传多个 """ #删 remove # book_obj=models.Book.objects.filter(pk=1).first() # book_obj.authors.remove(1) #记住指定的是虚拟字段 谁创建的谁调用 # book_obj.authors.remove(1,2) #可以指定多个参数 #删除也可以用对象 # book_obj=models.Book.objects.filter(pk=1).first() # author_obj = models.Author.objects.filter(pk=1).first() # author_obj1 = models.Author.objects.filter(pk=2).first() # book_obj.authors.remove(author_obj) # book_obj.authors.remove(author_obj, author_obj1) """ remove 在第三张关系表中删除数据 括号内既可以传主键字段也可以传数据对象 并且都支持传多个 """ #清空数据 clear # book_obj = models.Book.objects.filter(pk=2).first() # book_obj.authors.clear() # 清空当前书籍与作者的所有绑定关系 """ clear 在第三张关系表中清空数据 括号内无需传值 """
-
正反向查询的概念
正向查询 书籍对象查出版社对象 外键字段在书表中 一对多 # 正向查询 书籍对象查作者对象 外键字段在书表中 多对多 # 正向查询 作者对象查作者详情 外键字段在作者中 一对一 # 正向查询 反向查询 出版社查书籍对象 外键字段不在出版社表中 # 反向查询 作者查书籍对象 外键字段不在作者表中 # 反向查询 作者详情查作者 外键字段不在作者详情表中 # 反向查询 """ 查询数据的时候如果外键字段"在你的手上"则为正向查询 models.表名 看这个表名有外键字段则正向查询 如果外键字段不在则为反向查询 """ 口诀: 正向查询按外键字段 ... 反向查询按表名小写 ...
-
基于对象的跨表查询(子查询)
#子查询:一条sql语句查询结果给另一条sql语句当做查询的表用 正向查询按外键字段 ... 反向查询按表名小写 ... 后面有个-set 看情况添加 多的情况加 基于对象的正向查询 # 1.查询主键为2的书籍对应的出版社 # 分两步看 先查询书籍对象 # book_obj=models.Book.objects.filter(pk=2).first() #书籍对象查出版社对象 (当前在book表 外键字段在这 正向 .外键字段) # res=book_obj.publish # print(res,res.pk,res.name,res.addr) # 2.查询主键为3的书籍对应的作者 # 分两步看 先查询书籍对象 # book_obj=models.Book.objects.filter(pk=3).first() #书籍对象查作者对象 (当前在book表 外键字段在这 正向 .外键字段) # res=book_obj.authors #app01.Author.None 出现这个就加一个.all() # res=book_obj.authors.all() #<QuerySet [<Author: 这是对象:迪迦>, <Author: 这是对象:泰罗>]> # # print(res)#由于是queryset 列表套数据对象可以for循环拿数据对象然后.字段名 因为是多对多 获取了多个对象 # for i in res: # print(i.pk) # print(i.name) # print(i.age) # 3.查询迪迦的详情数据 # 分两步看 先查询作者对象 # author_obj=models.Author.objects.filter(name='迪迦').first() # 作者对象查询详情对象 (当前在作者表 外键字段在这 正向 .外键字段) # res=author_obj.author_detail # print(res,res.phone,res.addr) """ 小总结 基于对象的正向查询 数据对象点了外键字段之后 是否需要再点all 取决于关联的数据项有几个 单个无需点 多个则需要点 """ # 4.查询北方出版社出版的书籍 #先查询出版社对象 # publish_obj=models.Publish.objects.filter(name='北方出版社').first() #出版社对象查询书籍对象 (外键字段在书籍对象里 反向 .表面小写) # res=publish_obj.book #'Publish' object has no attribute 'book' 没有book这个字段 # res=publish_obj.book_set #需要加一个_set 发现app01.Book.None # res=publish_obj.book_set.all() #因为是多个对象 # print(res) 返回的是列表套数据对象 # for i in res : # print(i.title) # 5.查询泰罗写过的书籍 # 先查询作者对象 # author_obj=models.Author.objects.filter(name='泰罗').first() #作者对象查询书籍对象 (当前在author对象里,外键字段在书籍对象里 ,所以反向 .表名小写) # res=author_obj.book_set.all() #加了_set 和all # # print(res) # for i in res: # print(i.title) # 6.查询电话是110的作者姓名 # 先查询作者详情对象 # authordetail_obj=models.AuthorDetail.objects.filter(phone=110).first() # # 作者详情对象查询作者对象 (外键字段在作者 反向查询 .表名小写) # res=authordetail_obj.author #因为是一对一 就一个数据不需要_set 也不需要all # print(res.name) # print(res.age) """ 基于对象的反向查询 如果查询出来的数据对象可以有多个 那么需要 表名小写_set.all() 如果查询出来的数据对象只有一个 表名小写 """
-
基于双下划线的跨表查询(对应的sql连表操作)
#只能用一条orm语句 上面的是两句 # 1.查询主键为2的书籍对应的出版社 #也符合 正向反向查询 目前在book表 外键字段在这 正向 .外键字段 # values('publish'): 目前已经到了出版社这个表 拿什么字段直接__字段名 #返回的是一个列表套字典 # res=models.Book.objects.filter(pk=2).values('publish__name','publish__addr') # print(res) # 2.查询主键为3的书籍对应的作者 #先查pk=3的书籍对象 发现在book表查作者表 外键字段在自己这 正向查询 .外键字段名 # res=models.Book.objects.filter(pk=3).values('authors__name','authors__age') # print(res) # 3.查询迪迦的详情数据 #先查询用户对象 用户对象在查询用户数据对象 外键字段在自己这 正向查询 # res=models.Author.objects.filter(name='迪迦').values('author_detail__addr','author_detail__phone') # print(res) # 4.查询书籍pk为2的作者的电话 需要三个表 #先查询书籍对象 书籍对象查找作者对象 外键字段在自己这先到作者表__authors 在__author_detail 正向查询 # res= models.Book.objects.filter(pk=2).values('authors__author_detail__phone') # print(res) """ 总结 也看正向反向查询 正向 外键字段名__查询的字段名 values ('外键字段 就已经进入了这个表里 要什么直接__字段名就直接拿就好了') 可以到了第二张表继续__外键字段再到第三张表 """ # 5.查询北方出版社出版的书籍 #查出版社对象 出版社对象查询书籍对象 外键不在自己这 反向查询 # res=models.Publish.objects.filter(name='北方出版社').values('book__title') # print(res) # 6.查询泰罗写过的书籍 #先查询用户对象 用户对象查询书籍对象 外键字段不在自己这 反向查询 # res=models.Author.objects.filter(name='泰罗').values('book__title') # print(res) # 7.查询电话是110的作者姓名 #先查询用户详情对象 用户详情对象查找用户对象 外键字段不在自己这 反向查询 # res=models.AuthorDetail.objects.filter(phone=110).values('author__name') # print(res) ''' 总结 反向查询 小写表名__查询的字段名 '''
-
双下划线进阶操作
# 1.查询主键为2的书籍对应的出版社(不能点书籍) # 获取出版社对象数据的.filter方法里面先判断 # 我在出版社这,查找书籍对象 外键字段在书籍对象 反向查询 .表名小写__查询的条件 # res = models.Publish.objects.filter(book__pk=2) # print(res) #获取的是列表套数据对象<QuerySet [<Publish: 这是对象:东方出版社>]> # # res = models.Publish.objects.filter(book__pk=2).first() # print(res.name) #东方出版社 # 2.查询主键为3的书籍对应的作者 # 作者表对象 查询书籍对象 外键字段在书籍表 #反向查询 .表名小写__查询的条件 # res=models.Author.objects.filter(book__pk=3) # print(res) #<QuerySet [<Author: 这是对象:迪迦>, <Author: 这是对象:泰罗>]> # # res = models.Author.objects.filter(book__pk=3) #返回的是列表套数据对象 # for i in res : # print(i.name) #迪迦 泰罗 # 3.查询迪迦的详情数据 #先查询作者详情数据表 在用作者详情表查询作者表 外键字段不在自己这 反向查询 .表名__查询的字段 # res= models.AuthorDetail.objects.filter(author__name='迪迦') # print(res) #<QuerySet [<AuthorDetail: 这是对象:m78星云>]> # # res= models.AuthorDetail.objects.filter(author__name='迪迦').first() # print(res.phone,res.addr) #110 m78星云 # 4.查询书籍pk为2的作者的电话 用到了三张表 #先查询 作者详情表 作者详情表查询作者表 再书籍表 反向查询 #先点到作者表在点到书籍表在加上条件 # res=models.AuthorDetail.objects.filter(author__book__pk=2) # print(res) #<QuerySet [<AuthorDetail: 这是对象:m78星云>, <AuthorDetail: 这是对象:m98星云>]> # # for i in res: # print(i.phone) #110 120 # 5.查询北方出版社出版的书籍 # 创建书籍表对象 书籍表查询出版社对象 外键字段在自己这 正向查询.外建名字 # res=models.Book.objects.filter(publish__name='北方出版社') # #返回的是列表套数据对象 # print(res) #<QuerySet [<Book: 这是对象:活着>, <Book: 这是对象:我在精神病院学斩神>]> # # for i in res: #先循环出来数据对象 在点字段名 # print(i.title) #活着 我在精神病院学斩神 # 6.查询泰罗写过的书籍 # 书籍表 查询作者表 外键字段在自己这 正向查询 .外键字段名 # res= models.Book.objects.filter(authors__name='泰罗') # # 结果是一个列表套数据对象 # print(res) #<QuerySet [<Book: 这是对象:人性的弱点>, <Book: 这是对象:三国演义>]> # # for i in res: #把数据对象循环出来 然后点字段名 # print(i.title) #人性的弱点 三国演义 # 7.查询电话是110的作者姓名 # 作者表 查询作者详情表 外键字段在自己这 正向查询.外键字段 # res=models.Author.objects.filter(author_detail__phone=110) # print(res) #<QuerySet [<Author: 这是对象:迪迦>]> # res=models.Author.objects.filter(author_detail__phone=110).first() # print(res.name) #迪迦
-
聚合查询与分组查询
"""聚合查询:aggregate""" 聚合函数 aggregate max min sum count avg 需要先导入 from django.db.models import Max,Min,Sum,Count,Avg # 1.统计所有书籍的总价格 #主要用aggregate里面写聚合函数 # res=models.Book.objects.aggregate(Sum('price')) # print(res) #返回字典 # 2.统计所有书籍的总数 # res=models.Book.objects.aggregate(Count('pk')) # print(res) # 返回字典 # 3.统计价格最高的 # res=models.Book.objects.aggregate(Max('price')) # print(res) #还可以写多个 #res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('price'),Avg('price')) # print(res) """分组查询:annotate""" # 1.统计每一本书的作者个数 #每一本书籍分组 书籍表查 作者表 外键字段在自己这 正向查询 #使用annotate(别名=条件) 别名必须要起的 因为后面的values中需要使用 # res = models.Book.objects.annotate(author_num=Count('authors__pk')).values('author_num','title') # print(res) #返回的是列表套字典 # 2.统计出每个出版社卖的最便宜的书的价格 #每个 以出版社对象分组 出版社对象查 书对象 外键字段不在自己这 反向查询 表名小写 # res= models.Publish.objects.annotate(min_price=Min('book__price')).values('min_price','book__title') # print(res) # 3.统计不止一个作者的图书 #题目理解 每本图书的作者个数大于一 每本 以图书分组 # 图书分组 查作者 正向查询 先把每本图书个数拿出来 ,然后再筛选大于1的 # res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1) # for i in res: # print(i.title) # 4.查询各个作者出的书的总价格 #每个 以作者分组 #作者对象 查找书籍对象 反向查询 # res= models.Author.objects.annotate(sum_price=Sum('book__price')).values('sum_price','name') # print(res) """ 1.大的分组 models.表名.objects.annotate 按照models后面的表名分组(主键) 2.小的分组 models.表名.objects.values('price').annotate() 按照values括号内指定的字段分组 """
-
F查询与Q查询
#先导入 F查询主要操作数据类型
from django.db.models import F
# F的功能是获取数据库中字段原有的数据 比如在原有的数据进行增删改查
from django.db.models import F
# 1.将所有书籍的价格提升100块
#使用F
# models.Book.objects.update(price=F('price')+100)
# 2.将所有书籍名称后面加上爆款后缀
# 一般F用来操作数据对象 这个不常用
# from django.db.models.functions import Concat
# from django.db.models import Value
# models.Book.objects.update(title=Concat(F('title'), Value('爆款')))
# 3.查询库存数大于卖出数的书籍
# res=models.Book.objects.filter(kucun__gt=F('maichu'))
# print(res)
# for i in res:
# print(i.title)