一、多表操作

一对多字段的增删改(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. haproxy 2.0 dataplaneapi rest api 几个方便的问题排查接口

    在使用haproxy 2.0 dataplaneapi的时候,刚开始的时候我们可能需要进行调试,保证我们的配置在我们的系统环境中 是可以使用的,以下是自己在当前学习中为了排查问题会使用的几个api 创 ...

  2. 细说PHP-fpm

    在理解php-fpm之前,我们要先搞清楚几个关键词以及他们之间的关系:CGI FastCGI:(Fast Common Gateway Interface),即快速通用网关接口,是一种让交互程序与We ...

  3. linux高性能服务器编程 (三) --TCP协议详解

    第三章 IP协议详解 TCP协议是TCP/IP协议族中的另外一个重要的协议,与IP协议相比,TCP协议更高进应用层.一些重要的socket选项都和TCP协议相关.这一章主要从如下方面学习: 1)TCP ...

  4. CentOS 7 上 安装 jira

    步骤 .安装jdk8 https://www.cnblogs.com/sea-stream/p/10404360.html .安装mysql wget -i -c http://dev.mysql.c ...

  5. Spring Boot单元测试报错java.lang.IllegalStateException: Could not load TestContextBootstrapper [null]

    1 报错描述 java.lang.IllegalStateException: Could not load TestContextBootstrapper [null]. Specify @Boot ...

  6. Python开发:OpenCV版本差异所引发的cv2.findContours()函数传参问题

    一.问题如下: cv2.findContours()这个方法是用来找出轮廓值的: # cv2.findContours找出轮廓值,cv2.RETR_EXTERNAL表示图像的外轮廓 binary, c ...

  7. mybatis在sql中的CDATA区

    示例 <if test="startTime != null"> <![CDATA[ AND rra.create_time >= #{startTime} ...

  8. Spring中为什么继承了ApplicationContextAware接口就可以使用ApplicationContext对象?

    1.Spring中使用applicationContext对象 public class SpringContextUtil implements ApplicationContextAware { ...

  9. clickhouse 19.14.m.n简单测试

    ClickHouse is a column-oriented database management system (DBMS) for online analytical processing o ...

  10. zz 勵志貼,成功是努力加对的方向

    5-6年工作经验程序员初进大厂,如何适应工作? 李苦李 李苦李 ​ 华为 架构师 318 人赞同了该回答 泻药! 与题主背景非常相似. 本人毕业8年+,普通二本,学历不突出,非计算机专业. 唯一不同的 ...