一、多表操作

一对多字段的增删改(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查询的更多相关文章

  1. Django ORM 之基于对象、双下划线查询

    返回ORM目录 Django ORM 内容目录: 一. 基于对象的表查询 二. 基于双下划线的查询 三. 聚合查询 aggregate 四. 分组查询 annotate 一. 基于对象的表查询 1.正 ...

  2. Python--day69--单表查询之神奇的双下划线

    单表查询之神奇的双下划线: 单表查询之神奇的双下划线 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 models. ...

  3. Django 数据库查询集合(双下划线连表操作)

    Django是一款优秀的web框架,有着自己的ORM数据库模型.在项目中一直使用django数据库,写一篇文章专门记录一下数据库操作.略写django工程创建过程,详写查询过程.可以和sqlalche ...

  4. django之 基于queryset和双下划线的跨表查询

    前面篇随笔写的是基于对象的跨表查询:对象.objects.filter(...)  对象.关联对象_set.all(...)  -->反向 基于对象的跨表查询例如: book_obj= Book ...

  5. Django框架(七)—— 模板层:变量、过滤器、标签、自定义标签和过滤器

    目录 模板层:变量.过滤器.标签.自定义标签和过滤器 一.模板层变量 1.语法 2.使用 二.模板层之过滤器 1.语法 2.常用过滤器 3.其他过滤器 三.模板值标签 1.for标签 2.if标签 3 ...

  6. Django框架(七)-- 模板层:模板导入、模板继承、静态文件

    一.模板导入 要复用一个组件,可以将该组件写在一个文件中,在使用的时候导入即可 在模板中使用 1.语法 {% include '模板名字' %} 2.使用 ad.html页面 <div clas ...

  7. Django框架之第六篇(模型层)--单表查询和必知必会13条、单表查询之双下划线、Django ORM常用字段和参数、关系字段

    单表查询 补充一个知识点:在models.py建表是 create_time = models.DateField() 关键字参数: 1.auto_now:每次操作数据,都会自动刷新当前操作的时间 2 ...

  8. ORM( ORM查询13种方法3. 单表的双下划线的使用 4. 外键的方法 5. 多对多的方法 ,聚合,分组,F查询,Q查询,事务 )

    必知必会13条 <1> all(): 查询所有结果 <2> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或 ...

  9. Django (学习第二部 ORM 模型层)

    Django对数据库的操作 Django的 ORM 简介 ORM操作 (增删改查) ORM操作数据库的增删改查 ORM创建表关系 ORM中常用字段及参数 数据库的查询优化 ORM中如何开启事务 ORM ...

随机推荐

  1. ABP 05 创建Model 以及 相应的增删改查

    在core层 添加一个model,如图 2.在 EntityFrameworkCore 层的 DbContext 中添加 Menu 3.编译一下 准备把新增的Model迁移到数据库 打开 程序包管理器 ...

  2. [PHP]Laravel无法使用COOKIE和SESSION的解决方法

    COOKIE和SESSION的具体使用百度和官方文档上都有. 但是,文档里没有说明必须经过相应的中间件才能使用,百度搜索结果都是彼此copy的bullshit!!! 其实最终解决办法很简单,完全不是网 ...

  3. 一起学Makefile(二)

    Makefile基本概念示例 新建一个Code文件夹来测试一个简单的makefile 目录结构如下: 源码如下: makefile依赖: 一般在编写makefile之前都需要先分析清楚整个工程各个模块 ...

  4. JavaScript sort函数

    默认排序法则: 按照String类型ASCII码大小排序 如果要倒序排序,我们可以把大的数放前面: var arr = [10, 20, 1, 2]; arr.sort(function (x, y) ...

  5. 第09组 Alpha冲刺(5/6)

    队名:观光队 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 完成服务器连接数据库部分代码 展示GitHub当日代码/文档签入记录 接下来的计划 服务器网络请求,前端 ...

  6. mac mysql 使用注意事项

    mac mysql 使用注意事项 .安装 直接通过下载官网上的dmg安装包进行安装,mysql--osx10.-x86_64(我的安装文件) ,安装完成后在系统偏好设置里面有mysql选项,我们可以通 ...

  7. SLF4J使用,slf4j-api、slf4j-log4j12以及log4j的关系

    SLF4J不同于其他日志类库,与其它有很大的不同.SLF4J(Simple logging Facade for Java)不是一个真正的日志实现,而是一个抽象层( abstraction layer ...

  8. 自己动手实现DNS协议

    1. 主要内容 不说废话,直接进入正题.先说说本文本文的主要内容,好让你决定是否看下去: 介绍DNS是干什么的: 介绍DNS是如何工作的: 介绍DNS请求与响应的消息格式: 编程实现一个简单的DNS服 ...

  9. MySQL索引原理(二)

    MySQL索引原理 1.索引 索引是表的目录,在查找内容之前可以先在目录中查找索引位置,以此快速定位查询数据.对于索引,会保存在额外的文件中.索引是数据库中专门用于帮助用户快速查询数据的一种数据结构. ...

  10. cmd find命令用法

    Windows命令行(cmd)下快速查找文件(类似Linux下find命令) 2015年04月11日 10:50:43 开水 阅读数 62240 标签: 命令行cmdwindows 更多 个人分类:  ...