django学习第八天--多表操作删除和修改,子查询连表查询,双下划线跨表查询,聚合查询,分组查询,F查询,Q查询
1|0orm多条操作
1|1删除和修改
- 修改
在一对一和一对多关系时,和单表操作是一样的 一对一 一个作者对应一个信息 ad_obj = models.AuthorDetail.objects.get(id=1) models.Author.objects.filter(id=1).update(name='xx',属性名=模型类对象) models.Author.objects.filter(id=1).update(name='xx',ad=ad_obj) models.Author.objects.filter(id=1).update(name='xx',字段名=id字段值) models.Author.objects.filter(id=1).update(name='xx',ad_id=1) 一对多 一个出版社出多本书 pub_obj = models.Publish.objects.get(id=2) models.Book.objects.filter(id=1).update(title='水浒',属性名=模型类对象) models.Book.objects.filter(id=1).update(title='水浒',pub=pub_obj) models.Book.objects.filter(id=2).update(title='三国',字段名=id字段值) models.Book.objects.filter(id=2).update(title='三国',pub_id=2) 多对多修改 book_obj = models.Book.objcets.get(id=4) #用book_obj模型类对象,然后点属性(.authors)的方式操作第三张表 book_obj.authors.set('3')#参数要是可迭代类型数据 book_obj.authors.set([3,])#更新多个记录 set执行的步骤: 1.先执行clear清空 2.再执行add添加 book_obj = models.Book.objects.get(id=1) book_obj.authors.set([4,])
- 删除
一对一和一对多删除一样 delete方法 models.Author.objects.filter(id=1).delete() models.AuthorDetail.objects.filter(id=1).delete() 多对多删除remove book_obj = models.Book.objects.get(id=1) author_obj = models.Author.objects.get(id=2) 下面orm语句意思为在多对多关系表中删除了书籍id为1的,作者id为2的记录 #通过Book得到的模型类对象点属性(.authors)操作第三张表 book_obj.authors.remove(2) #删除单条 book_obj.authors.remove(2,3)#删除多条
- 清空
多对多 #将当前书籍对应的所有作者在多对多关系表中的关系记录,全部删除 book_obj = models.Book.objects.get(id=1) book_obj.authors.clear()
2|0子查询和连表查询
2|1基于对象的跨表查询(子查询)
一对一查询 正向查询 关系属性写在哪个表里面,那么通过这个表的数据,去查询关联的另外一张表的数据,就叫作正向查询,反之就是反向查询 #正向查询使用关联属性名称 #查询一下王振这个作者的手机号 author_obj = models.Author.objects.get(name='王振') author_obj.ad #找到了author_obj关联的作者详细信息表里面的对应记录 主表模型类对象(author_obj).主表的关联属性名称(ad).从表属性名(telephone) print(author_obj.ad.telephone) #反向查询 反向查询用关联它的模型类的名称小写 查询一下地址在上海的那个作者是谁 从表->主表 author_detail_obj = models.AuthorDetail.objects.filter(address='上海').first() #filter过滤后的是quertset类型,用first取第一个模型类对象 从表的模型类对象.主表的模型类名称小写.主表属性名 print(author_detail_obj.author.name) ##########一对多######### #正向查询 #使用关联属性查询 #查询一下少年阿宾是哪个出版社出版的 book_obj = models.Book.objects.get(title='少年阿宾') Book类的模型类对象.关联属性.name print(book_obj.pub.name) #反向查询 #模型类小写_set #查询一下伟哥出版社出版了哪些书 pub_obj = models.Publish.objects.get(name='伟哥出版社') pub_obj.book_set #可能为多条记录,所以模型类名小写_set #类似于objects控制器 print(pub_obj.book_set.all().values('title')) #查询结果不会自动去重 ######多对多###### #正向查询 #使用属性来查 #查询一下金陵第二步这本书谁写的 book_obj = models.Book.objects.get(title='金陵第二部') Book类的模型类对象.关联属性名称.all().values('name') print(book_obj.authors.all().values('name')) #反向查询 #使用模型类名小写_set 查询一下谢晨写了哪些书 author_obj = models.Author.objects.get(name='谢晨') print(author_obj.book_set.all().values('title'))
3|0查看原生sql的方式
- 1.query 适用于大部分
- 2.在settings配置文件中写上如下内容,就能够自动打印出我们执行orm语句对应的sql
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
- 3.通过django配置的连接mysql的管道来查看(pymysql)
from app01 import models def add_book(request): book_obj = models.Book(title='python',price=123) book_obj.save() from django.db import connection #通过这种方式也能查看sql语句 print(connection.queries) return HttpResponse('OK')
4|0基于双下划线的跨表查询(连表操作)
原生sql写法 哪个表在前哪个表在后没区别 select * from t2 inner join t1 on t1.t2_id = t2.id; select * from t1 inner join t2 on t1.t2_id = t2.id;
- 一对一
查询一下谢思敏这个作者的家庭地址 正向操作,使用属性 ret = models.Author.objects.filter(过滤条件).values('主表属性名__从表属性名') ret = models.Author.objects.filter(name='谢思敏').values('ad__address') #<QuerySet [{'ad__address': '美国'}]>类型 反向操作,使用表名小写 ret = models.AuthorDetail.objects.filter(主表表名小写__过滤条件).values('从表属性名') ret = models.AuthorDetail.objects.filter(author__name='谢思敏').values('address') #<QuerySet [{'address': '美国'}]>类型
- 一对多
查询一下少年阿宾是哪个出版社出版的 正向操作 使用关联属性 #这类的正向操作,注意看关联的属性名在哪个表里,哪个表就是主表 ret = models.Book.objects.filter(过滤条件).values('关联属性名__从表属性名') ret = models.Book.objects.filter(title='少年阿宾').values('pub__name')#<QuerySet [{'pub__name': '橘子成人出版社'}]> 反向操作 ret = models.Publish.objects.filter(主表类名小写__过滤条件).values('从表属性名') ret = models.Publish.objects.filter(book__title='少年阿宾').values('name')#<QuerySet [{'name': '橘子成人出版社'}]>
- 多对多
查询一下金陵第二部这本书谁写的 正向操作 使用关联属性 ret = models.Book.objects.filter(title='金陵第二部').values('Book类模型关联属性__author表属性名') ret = models.Book.objects.filter(title='金陵第二部').values('authors__name') #<QuerySet [{'authors__name': '谢思敏'}, {'authors__name': '谢晨'}]> 反向操作 使用类名小写 ret = models.Author.objects.filter(主表类名小写__过滤条件).values('从表属性名') ret = models.Author.objects.filter(book__title='金陵第二部').values('name') #<QuerySet [{'name': '谢思敏'}, {'name': '谢晨'}]>
5|0聚合查询(aggregate)
##########聚合查询aggregate########### 统计一下所有书籍的平均价格 max min avg count sum 需要先导入 from django.db.models import Max,Min,Avg,Count,Sum ret = models.Book.objects.aggregate(Avg('price')) print(ret)#普通字典类型{'price__avg': 43.925} ret = models.Book.objects.all().aggregate(a=Avg('price'),b=Max('price')) print(ret)#{'price__avg': 43.925, 'price__max': Decimal('88.88')} , {'a': 43.925, 'b': Decimal('88.88')} #aggregate方法可以看为是orm语句的结束语句,结果为普通字典类型,不能继续调用queryset或者模型类对象提供的方法了,也就是aggregate必须放在最后,另外里面的聚合函数可以赋值给变量
6|0分组查询(annotate)
###########分组查询########### 查询一下每个出版社出版书的平均价格 ret = models.Book.objects.values('要分组的字段名').annotate(聚合函数) ret = models.Book.objects.values('pub_id').annotate(a=Avg('price'))#只能获取到values指定的字段和统计结果数据 ret = models.Book.objects.values('pub_id','id').annotate(a=Avg('price'))#多条件分组pub_id和id值相同的算为一组 values('pub__name')#就是通过Book类的属性名跨表操作另外一张表的name ret = models.Book.objects.values('pub__name').annotate(a=Avg('price'))#以出版社名称分组 #推荐使用下面的因为获取到模型类对象就可以用它所有的属性数据 ret = models.Publish.objects.annotate(变量a=聚合函数Avg('要关联的另外一张表的类名小写__要操作的属性')) ret = models.Publish.objects.annotate(a=Avg('book__price'))#返回结果是Publish的模型类对象,这个模型类对象里面包含了Publish的所有属性数据,还有annotate的统计结果数据 ret = models.Publish.objects.annotate(a=Avg('book__price')).values('name','a') 原生sql,伪代码 select publish.name,Avg(book.price) from publish inner join book on publish.id = book.pub_id group by publish.id. select avg(price) from book group by pub_id;
7|0F查询 主要针对本表的多个字段进行比较时使用
########F查询######### from django.db.models import F #查询一下点赞数在于评论数的书籍 models.Book.objects.filter(dianzan__gt=comment) obj_list = models.Book.objects.all().values() a = [] for i in obj_list: if i.dianzan > i.comment: a.append(i) print(a) #上面写法太麻烦了 F查询可以用来做本表不同字段之间的一个比较 ret = models.Book.objects.filter(dianzan__gt=F('comment')) print(ret) F可以用来对本表数据进行一些同一操作(四则运行都支持) 将所有的书籍上调10块钱 models.Book.objects.all().update(price=F('price')+10)
8|0Q查询 可以进行多条件查询,查询关系可以是 或与非
from django.db.models import F #查询书名中包含少年两个字的并且评论数大于20的书籍 ret = models.Book.objects.filter(title__contains='少年',comment__ge=20) #filter中逗号分隔的条件,默认是and的关系 print(ret)#<QuerySet [<Book: 少年阿宾2>]> #想进行或的关系查询需要借助到我们Q查询Q 查询书名中包含少年两个字的或者评论数大于20的书籍 ret = models.Book.objects.filter(Q(title__contains='少年')|Q(comment__gt=20)) 查询书名中包含少年两个字的或者评论数大于20的,并且点赞数大于等于80的 ret = models.Book.objects.filter(Q(title__contains='少年')|Q(comment__gt=20),dianzan__gte=80) #注意,如果结合逗号来进行and的关系查询,那么必须将没有Q包裹的查询条件放在Q包裹的查询条件后面 下面这张方式也可以,Q查询可以多层嵌套使用 # ~取反 &and关系 |or关系 ret = models.Book.objects.filter(Q(Q(title__contains='少年')|Q(comment__gt=20)) & ~Q(dianzan__gte=80))
__EOF__

本文作者:404 Not Found
本文链接:https://www.cnblogs.com/weiweivip666/p/13356732.html
关于博主:可能又在睡觉
版权声明:转载请注明出处
声援博主:如果看到我睡觉请喊我去学习
本文链接:https://www.cnblogs.com/weiweivip666/p/13356732.html
关于博主:可能又在睡觉
版权声明:转载请注明出处
声援博主:如果看到我睡觉请喊我去学习
-------------------------------------------
个性签名:代码过万,键盘敲烂!!!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人