Django框架第七篇(模型层)--多表操作:一对多/多对多增删改,跨表查询(基于对象、基于双下划线跨表查询),聚合查询,分组查询,F查询与Q查询
一、多表操作
一对多字段的增删改(book表和publish表是一对多关系,publish_id字段)
如果是数据库实际字段就传数字,不是就传对象
增 create
publish_id 传数字 (publish_id是数据库显示的字段名,外键在book表)
models.Book.objects.create(title='三国演义',price=200,publish_id=1) #publish_id是mysql数据库中显示的字段名
publish直接传出版社对象 (publish是models.py设计表字段名)
#查询到的publish表主键为2的对象
publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.create(title='红楼梦',price=250,publish=publish_obj) #publish是models.py中的字段名
改 update
传数字的
models.Book.objects.filter(pk=2).update(publish_id=3) #修改publish_id=3
传对象的
#查询publish表中要修改的对象主键值为2
publish_obj = models.Publish.objects.filter(pk=2).first()
#修改
models.Book.objects.filter(pk=1).update(publish=publish_obj) #把pk=1的数据publish字段更换
删 delete
models.Publish.objects.filter(pk=2).delete() # 默认都是级联更新 级联删除
多对多字段的增删改(book表和author表是多对多关系,新生成一张表)
增 add()
要给主键为1的书籍添加两个作者
传数字
#先查询主键为1的书籍
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.book_author) 这个book_author是book表中多对多虚拟字段,book_author是字段名 #对象点击多对多虚拟字段,会直接跨到多对多的第三张表
book_obj.book_author.add(1) 传数字 给书籍1增加主键为1的作者
book_obj.book_author.add(2,3) 一次性给书籍1增加主键为2,3的作者
传对象
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.book_author.add(author_obj) 传对象
book_obj.book_author.add(author_obj1,author_obj2) add()
是给书籍添加作者 括号内既可以传数字也可以传对象,但是不要混着用
并且支持一次性传多个 逗号隔开即可
多对多表(mysql)
改 set()
将主键为1的书籍对象作者修改为2,3
传数字
#也是先查询出主键为1的书籍
book_obj = models.Book.objects.filter(pk=1).first() book_obj.book_author.set([2,])
book_obj.book_author.set([2,3]) 传对象
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.book_author.set([author_obj,])
book_obj.book_author.set([author_obj, author_obj1, author_obj2])
注意:set()括号内 传一个可迭代对象 (******)
可迭代对象中 可以是多个数字组合
也可以是多个对象组合
但是不要混着用!!!
上一步主键为1的书籍绑定了三个作者,现在改为两个,就是把多余的删除掉
删 remove()
删除主键值为1的书籍作者2
传数字
#也是先查询出主键为1的书籍
book_obj = models.Book.objects.filter(pk=1).first() book_obj.book_author.remove(2)
book_obj.book_author.remove(2,3) 传对象
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.book_author.remove(author_obj)
book_obj.book_author.remove(author_obj1,author_obj2)
remove()括号内既可以传数字 也可以传对象
并且支持传对个 逗号隔开即可
删除作者2
清空 clear()
将某本书跟作者的关系全部清空
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.book_author.clear() # 清空当前书籍与作者的所有关系
多对多增删改总结(******)
add()
set()
remove()
上面三个都支持传数字 或者对象 并且可以传多个 但是set需要传可迭代对象 clear()
clear括号内不需要传任何参数
二、跨表查询(******) 就是前面缺的查询
正向与反向的概念
一对一
正向:author---关联字段在author表里--->authordetail 按字段
反向:authordetail---关联字段在author表里--->author 按表名小写 一对多
正向:book---关联字段在book表里--->publish 按字段,查询多个对象.all()
反向:publish---关联字段在book表里--->book 按表名小写,查询多个对象_set.all() 多对多
正向:book---关联字段在book表里--->author 按字段,查询多个对象.all()
反向:author---关联字段在book表里--->book 按表名小写,查询多个对象_set.all() 正向查询按外键字段
反向查询按表名小写
基于对象的跨表查询(子查询:将一张表的查询结果当做另一个查询语句的条件)
1.查询书籍id是1的出版社名称 (一对多查询)正向查询
先查询出id为1的书籍对象
book_obj = models.Book.objects.filter(pk=1).first() print(book_obj.publish.name) #正向查询,因为publish在book表中,直接对象.字段名就能获取到
print(book_obj.publish.addr)
2.查询书籍id是2的作者姓名 (多对多查询) 正向查询
先查询出书籍id为2的对象
book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.book_author) #正向查询 #app01.Author.None
print(book_obj.book_author.all()) #<QuerySet [<Author: jason>, <Author: egon>]>
res =book_obj.book_author.all()
for r in res:
print(r.name) #jason egon
3.查询作者是jason的家庭住址 (一对一查询)正向查询
#先查作者名的jason的对象
author_obj = models.Author.objects.filter(name='jason').first() print(author_obj.author_detail.addr) #正向查询 在Author表中有author_detil字段
4.查询出版社是东方出版社出版的书籍 (一对多查询)反向查询
#先查询出出版社是东方出版社的对象
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set.all()) #<QuerySet [<Book: 三国演义>, <Book: 西游记>]> #需要加.all()才能获取到结果 res = publish_obj.book_set.all()
for r in res:
print(r.title) #三国演义 西游记
5.查询作者是jason的写过的所有的书籍 (多对多查询)反向查询
#先查询作者是jason的对象
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: 红楼梦>]> res=author_obj.book_set.all()
for r in res:
print(r.title)
6.查询电话号码是130的作者姓名 (一对一查询)反向查询
#先查询电话号码是130的对象
author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first() print(author_detail_obj.author.name) #反向查询
print(author_detail_obj.author.addr)
需要注意:正向查询多个的时候,需要加.all() 在反向查询的结果是多个的时候,需要加_set.all() (******)
7.查询书籍id为1的作者的电话号码 (多对多查询)正向查询
book_obj = models.Book.objects.filter(pk=1).first()
author_list = book_obj.book_author.all() #多个结果时候用all()
for author_obj in author_list:
print(author_obj.author_detail.phone) 直接.就能出结果
基于双下划线的跨表查询(连表操作)
-正向:按字段,跨表可以在filter,也可以在values中
-反向:按表名小写,跨表可以在filter,也可以在values中
1.查询jason作者的手机号 (一对一查询)正向查询
models.Author.objects.filter(name='jason').values('author_detail__phone') #author_detail是Author的字段(所以是正向查询)
2.查询jason作者的手机号 反向查询
models.AuthorDetail.objects.filter(author__name='jason').values('phone') #反向查询 author是小写表名
3.查询jason这个作者的年龄和手机号 (一对一查询)正向查询
models.Author.objects.filter(name='jason').values('age','author_detail__phone')
4.查询jason这个作者的年龄和手机号 反向查询
models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
5.查询手机号是130的作者年龄 (一对一查询)正向查询
models.Author.objects.filter(author_detail__phone=130).values('age')
6.查询手机号是130的作者年龄 反向查询
models.AuthorDetail.objects.filter(phone=130).values('author__age')
7.查询书籍id是1的作者的电话号码
models.Book.objects.filter(pk=1).values('book_author__author_detail__phone')
models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__普通字段')
只要表里面有外键字段 你就可以无限制跨多张表
1.查询出版社为北京出版社的所有图书的名字和价格 (一对多查询)正向
models.Book.objects(publish__name='北京出版社').values('title','price')
2.查询出版社为北京出版社的所有图书的名字和价格 (一对多查询)反向
models.Publish.objects.filter(name='北京出版社').values('book__name','book__price')
3.查询北京出版社出版的价格大于19的书
models.Book.objects.filter(price__gt=19,publish__name='北京出版社').values('title')
三、聚合查询(aggregate)
from django.db.models import Max,Min,Count,Avg,Sum #查询总和,平均,最大,最小 res = models.Book.objects.aggregate(Sum('price'))
res1 = models.Book.objects.aggregate(Avg('price'))
res2 = models.Book.objects.aggregate(Count('price'))
res3 = models.Book.objects.aggregate(Max('price'))
res4 = models.Book.objects.aggregate(Min('price'))
res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price')) #也可以放在一个里面写
四、分组查询 (annotate)
1.统计每一本书的作者个数
from django.db.models import Max, Min, Count, Avg, Sum
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
#book表根据authors分组求和,author_num是取的别名,values是控制台打印的值
2.统计每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
4.查询每个作者出的书的总价格
res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
五、F查询与Q查询
F查询的本质就是从数据库中获取某个字段的值,之前查询等号后面的条件都是我们人为输入的,现在变成了需要从数据库中获取数据放在等号后面
查询库存量大于卖出量的书籍
from django.db.models import F
res = models.Book.objects.filter(kucun__gt=F('maichu')) #kucun和maichu都是Book表的字段
将书籍库存数全部增加1000
models.Book.objects.update(kucun=F('kucun')+1000)
把所有书名后面加上'新款' (注意修改char类型的字段不能按照上面那种方式,需要使用Concat,加上拼接值value)
from django.db.models.functions import Concat
from django.db.models import Value ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
models.Book.objects.update(title = F('title')+'新款') # 不能这么写
Q查询 (filter里面条件都是与,Q支持与或非)
查询书籍名称是三国演义或者价格是444
from django.db.models import Q
res = models.Book.objects.filter(title='三国演义',price=444.44) # filter只支持and关系
res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号 那么还是and关系
res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444)) #或者关系
res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444)) #查询除了title是三国演义,或者价格是444的书籍
Q的高级用法
from django.db.models import Q
q = Q()
q.connector = 'or' # 修改查询条件的关系 默认是and
q.children.append(('title__contains','三国演义')) # 往列表中添加筛选条件
q.children.append(('price__gt',444)) # 往列表中添加筛选条件
res = models.Book.objects.filter(q) # filter支持你直接传q对象 但是默认还是and关系
print(res)
Django框架第七篇(模型层)--多表操作:一对多/多对多增删改,跨表查询(基于对象、基于双下划线跨表查询),聚合查询,分组查询,F查询与Q查询的更多相关文章
- Django ORM 之基于对象、双下划线查询
返回ORM目录 Django ORM 内容目录: 一. 基于对象的表查询 二. 基于双下划线的查询 三. 聚合查询 aggregate 四. 分组查询 annotate 一. 基于对象的表查询 1.正 ...
- Python--day69--单表查询之神奇的双下划线
单表查询之神奇的双下划线: 单表查询之神奇的双下划线 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 models. ...
- Django 数据库查询集合(双下划线连表操作)
Django是一款优秀的web框架,有着自己的ORM数据库模型.在项目中一直使用django数据库,写一篇文章专门记录一下数据库操作.略写django工程创建过程,详写查询过程.可以和sqlalche ...
- django之 基于queryset和双下划线的跨表查询
前面篇随笔写的是基于对象的跨表查询:对象.objects.filter(...) 对象.关联对象_set.all(...) -->反向 基于对象的跨表查询例如: book_obj= Book ...
- Django框架(七)—— 模板层:变量、过滤器、标签、自定义标签和过滤器
目录 模板层:变量.过滤器.标签.自定义标签和过滤器 一.模板层变量 1.语法 2.使用 二.模板层之过滤器 1.语法 2.常用过滤器 3.其他过滤器 三.模板值标签 1.for标签 2.if标签 3 ...
- Django框架(七)-- 模板层:模板导入、模板继承、静态文件
一.模板导入 要复用一个组件,可以将该组件写在一个文件中,在使用的时候导入即可 在模板中使用 1.语法 {% include '模板名字' %} 2.使用 ad.html页面 <div clas ...
- Django框架之第六篇(模型层)--单表查询和必知必会13条、单表查询之双下划线、Django ORM常用字段和参数、关系字段
单表查询 补充一个知识点:在models.py建表是 create_time = models.DateField() 关键字参数: 1.auto_now:每次操作数据,都会自动刷新当前操作的时间 2 ...
- ORM( ORM查询13种方法3. 单表的双下划线的使用 4. 外键的方法 5. 多对多的方法 ,聚合,分组,F查询,Q查询,事务 )
必知必会13条 <1> all(): 查询所有结果 <2> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或 ...
- Django (学习第二部 ORM 模型层)
Django对数据库的操作 Django的 ORM 简介 ORM操作 (增删改查) ORM操作数据库的增删改查 ORM创建表关系 ORM中常用字段及参数 数据库的查询优化 ORM中如何开启事务 ORM ...
随机推荐
- 爬虫 -- UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe6 in position 301: unexpected end of data
errors参数有3个值:strict, ignore, replace html.decode("utf-8"),这种形式有时会报错,那么修改为下面形式,将decode函数 ...
- Fiborial 题解——2019.10.14
一看到这个题 就感觉...cao,, 什么东西...??! 然后就开始暴力求Fn 然鹅我并不会写高精(我太菜了) 只能求到大概10左右 在吧Fn给质因数分解 求出其因子个数 妄图找到什么有关的规律 但 ...
- IIS服务器简单搭建
概况 系统:WIN10企业版 开发工具:VS2013 - VS2017 IIS版本:IIS6.0 安装 安装步骤如图: 这里需要注意一点信息服务器下默认web管理工具只有iis控制台勾上了,也就意味 ...
- JS中判断空对象
js 判断空对象 首先要区分一个概念,空对象和空引用: 空对象:{}是指不含任何属性的对象,当然对象属性包括字面值和函数. 空引用:obj=null 是指变量值指向null变量,当然在js默认不赋值的 ...
- windows自动修复失败,无法启动
Windows10操作系统于2015年7月29日正式发布,此后,win10也就成了新上市的笔记本电脑或者台式机电脑的预装操作系统!win10系统给我们带了全新的体验,当然也带来了一定的烦恼!就拿win ...
- 【cf比赛记录】Codeforces Round #601 (Div. 2)
Codeforces Round #601 (Div. 2) ---- 比赛传送门 周二晚因为身体不适鸽了,补题补题 A // http://codeforces.com/contest/1255/p ...
- python: isdigit int float 使用
>>> num1 = '2.0' >>> print num1.isdigit() False >>> num2 = ' >>> ...
- 《Genius》
Einstein is genius. 爱因斯坦是天才,这是一个毫无疑问的命题.他在专利局空闲之余写下的相对论,可以让我们学习很久一段时间,而且还不一定能学懂. 这部十集的电视连续剧是 ...
- 批归一化(Batch Normalization)
之前在几篇博客中说到了权重共享,但都觉得不够全面,这里做个专题,以后有新的理解都在此更新. 1. 减少运算只是锦上添花之前说到权重共享可以减少运算,是的,但这样说好像是可有可无,只是运算量大小的问题, ...
- win10-mysql卸载干净
本文介绍,在Windows10系统下,如何彻底删除卸载MySQL 1.停止MySQL服务 开始——所有应用——Windows管理工具——服务,将MySQL服务停止. 2.卸载mysql server ...