一、创建多表模型

一对一:OneToOneField

一对多:ForeignKey

多对多:ManyToManyField

  • 创建表时,会自动添加一个nid字段,并且自增,所以id可以不用手动创建

  • OneToOneField和ForeignKey会自动在后面加上" _id "

  • ManyToManyField会自动创建第三张表

  • 创建表的类,OneToOneField、ForeignKey和ManyToManyField中的to后的主表,
    1、如果用双引号包裹,那么创建主表的类在上在下都可以

    2、如果不用双引号包裹,那么创建主表的类就必须在从表的上方

二、一对多增删改表记录

class Publish(models.Model):
# id如果不写,会自动生成,名字叫nid,并且自增
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
email = models.EmailField() class Author(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
# 数字类型
sex = models.IntegerField()
# to='AuthorDetail' 加引号,这个表能找到就可以,不用引号,类必须在上面定义
authordetail = models.OneToOneField(to='AuthorDetail', to_field='id') def __str__(self):
return self.name class AuthorDetail(models.Model):
id = models.AutoField(primary_key=True)
phone = models.CharField(max_length=32)
addr = models.CharField(max_length=64) class Book(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.ForeignKey(to=Publish, to_field='id') authors = models.ManyToManyField(to=Author) def __str__(self):
return self.name

1、一对多添加记录

(1)通过 _id 来添加记录

models.Book.objects.create(name='红楼梦',price=20.0,publish_id=1)

(2)通过对象添加记录

# pk 表示主键,一旦主键改变,还是会找到对应的主键来获取对象
publish = models.Publish.objects.filter(pk=1).first()
models.Book.objects.create(name='红楼梦',price=34.5,publish=publish)

2、一对多删除记录

删除记录同单表删除记录一样

models.Book.objects.filter(name='红楼梦').first().delete()

3、一对多修改记录

(1)通过queryset对象的update方法修改

# 方式一:通过 _id 修改
models.Book.objects.filter(pk=1).update(name='西游记',publish_id=1) # 方式二:通过对象修改
publish = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(name='西游记',publish=publish)

(2)通过对象的属性修改,调用对象的save()方法保存

# 方式一:通过 _id 修改
book = models.Book.objects.filter(pk=1).first()
add()    # 可以传对象,可以传id,可以传多个

book.publish_id = 2
book.save() # 方式二:通过对象修改
publish = models.Publish.objects.filter(pk=2).first()
book.publish = publish
book.save()

三、一对一增删改记录

一对一的增删改记录和一对多的方法相同,参考一对多的增删改记录

四、多对多增删改记录

1、多对多增加记录

add()    # 可以传对象,可以传id,可以传多个

(1)通过对象添加记录

# 为红楼梦这本书添加一个作者
tom = models.Author.objects.filter(name='tom').first()
book = models.Book.objects.filter(name='红楼梦').first()
tony = models.Author.objects.filter(name='tony').first()
jack = models.Author.objects.filter(name='jack').first()
book.authors.add(tom)
# 一次添加两个作者,中间用逗号隔开
book.authors.add(tony,jack)

(2)通过 id 添加记录

book = models.Book.objects.filter(name='红楼梦').first()
book.authors.add(1)
# 一次添加两个作者,中间用逗号隔开
book.authors.add(1,2)

2、多对多删除记录

remove()    # 可以传对象,可以传id,可以传多个

(1)通过对象删除记录

# 删除红楼梦作者名字是tom的作者
tom = models.Author.objects.filter(name='tom').first()
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.remove(tom)

(2)通过id删除记录

# 删除红楼梦作者id是1、2的两个作者
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.remove(1,2)

3、多对多清空记录

clear()    # 没有参数
# 清除红楼梦的所有作者
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.clear()

4、多对多修改记录

set()    # 先清空在增加,必须传列表,列表里面可以是对象,可以是id

(1)通过对象修改记录

# 修改红楼梦作者名字为tom
tom = models.Author.objects.filter(name='tom').first()
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.set([tom,])

(2)通过id修改记录

# 修改红楼梦作者为作者id是1、2的作者
book = models.Book.objects.filter(name='红楼梦').first()
book.authors.set([1,2])

五、基于对象的跨表查询--多次查询、子查询

正向查询和反向查询

正向查询:关联字段在从表,由从表查询主表中的数据    -----> 按字段查询
反向查询:关联字段在从表,由主表查询从表中的数据 -----> 按表名小写查询

1、一对一基于对象的跨表查询

正向:正向查询按 字段
反向:反向查询按 表名小写
# 1.正向 查询红楼梦这本书的出版社邮箱
book=Book.objects.filter(name='红楼梦').first()
# book.publish 就是出版社对象
pulish=book.publish
print(pulish.email) # 2.反向 查询地址是北京的出版社出版的图书
publish=Publish.objects.filter(addr='北京').first()
# publish.book_set.all() 拿出所有的图书
books=publish.book_set.all()
# 统计一下条数
books=publish.book_set.all().count()
print(books)

3、多对多基于对象的跨表查询

正向:正向查询按 字段.all()
反向:反向按 表名小写_set.all()
# 1.查询红楼梦这本书所有的作者
book=Book.objects.filter(name='红楼梦').first()
book.authors.all() # 是所有的作者,是一个queryset对象,可以继续点
print(book.authors.all()) # 2.查询lqz写的所有书
lqz=Author.objects.filter(name='lqz').first()
books=lqz.book_set.all()
print(books)

六、基于双下划线的跨表查询

1、一对一的基于双下划线的跨表查询

正向:按 字段,跨表可以在filter,也可以在values中
反向:按 表名小写,跨表可以在filter,也可以在values中
# 1.查询tom作者的手机号   正向查询  跨表的话,按字段
# 以author表作为基表
ret=Author.objects.filter(name='tom').values('authordetail__phone')
print(ret) # 2.以authordetail作为基表 反向查询,按表名小写 跨表的话,用表名小写
ret=AuthorDetail.objects.filter(author__name='tom').values('phone')
print(ret)

3、多对多的基于双下划线的跨表查询

正向:按 字段,跨表可以在filter,也可以在values中
反向:按 表名小写,跨表可以在filter,也可以在values中
# 查询红楼梦的所有作者名字
# 1.以Book为基表
ret=Book.objects.filter(name='红楼梦').values('authors__name')
print(ret) # 2.以Author为基表
ret = Author.objects.filter(book__name='红楼梦').values('name')
print(ret)

4、连续跨表查询

一直用双下划线 __ 获取字段

# 查询红楼梦这本书所有的作者的手机号
book=Book.objects.filter(name='红楼梦').first()
authors=book.authors.all()
for author in authors:
authordetail=author.authordetail
print(authordetail.phone) # 方法二,使用连续跨表
ret = Book.objects.filter(name='红楼梦').values('authors__authordetails__phone')
print(ret)

七、聚合查询

1、什么聚合

用聚合函数来汇总多条信息

2、语法

from django.db.models import Avg,Sum,Count,Max,Min
aggregate(*args, **kwargs)

3、聚合函数使用

# 聚合函数
Max('price'),Min('price'),Avg('price'),Sum('price')
# 计算所有图书的平均价格
ret = models.Book.objects.all().aggregate(Avg('price'))
print(ret) # 计算图书的最高价格,最低价格,平均价格,总价
ret = models.Book.objects.all().aggregate(Max('price'),Min('price'),Avg('price'),Sum('price'))
print(ret)

八、分组查询

1、关键注意点

values在前,表示group by,在后,表示取值
filter在前,表示过滤(where),在后,表示having(对分组之后的结果再进行过滤)

2、分组查询案例

# 查询所有作者写的书的总价格大于26的
# filter()在annotate后面,表示对分组后的结果进行筛选,相当于having
# annotate前的values()表示按该字段分组,相当于group by,可以省略,默认会按Author的id分组
# 后面的values()表示取值
ret=Author.objects.all().values('pk').annotate(s=Sum('book__price')).filter(s__gt=26).values('name','s') 等价于 ret=Author.objects.all().annotate(s=Sum('book__price')).filter(s__gt=26).values('name','s')
# 查询各个作者出的书的总价格
# s相当于给求和结果取名字,在vlaues取值中,可以引用
ret = Author.objects.all().annotate(s=Sum('price')).values('name','s')
print(ret)
# 统计不止一个作者的图书
ret=Book.objects.all().values('pk').annotate(c=Count('authors')).filter(c__gt=1).values('name','c')
print(ret) 等价于 ret = Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num')
print(ret)

九、F查询和Q查询

1、F查询

(1)什么是F查询

如果要对两个字段的值作比较,就不能直接比较,必须要借助F() 的实例,它可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

(2)语法

from django.db.models import F
fliter(commit_num__gt=F('read_num'))

(3)F查询的使用

# 查询评论数大于阅读数的书
book = models.Book.objects.filter(commit_num__gt=F('read_num')).values('name') # 把所有书的评论数加1
models.Book.objects.all().update(commit_num=F('commit_num')+1)

2、Q查询

(1)什么是Q查询

对两个字段的值进行 且、或、非 运算,不能直接运算,需要用Q()的实例

(2)语法

# 且  ----->  &
# 或 -----> |
# 非 -----> ~
from django.db.models import Q
fliter(Q(name='tom')|Q(name='tony'))

(3)Q查询的使用

# 查询不是tom写的书的名字
ret = models.Book.objects.filter(~Q(authors__name='tom')).values('name') # 查询作者名字是tom或者名字是tony的书
ret = models.Book.objects.filter(Q(authors__name='tom')|Q(authors__name='tony')).values('name')

  

Django框架(九)-- 多表操作:一对一、一对多、多对多的增删改,基于对象/双下划线的跨表查询、聚合查询、分组查询、F查询与Q查询的更多相关文章

  1. Django框架(十)—— 多表操作:一对一、一对多、多对多的增删改,基于对象/双下划线的跨表查询、聚合查询、分组查询、F查询与Q查询

    目录 多表操作:增删改,基于对象/双下划线的跨表查询.聚合查询.分组查询.F查询与Q查询 一.创建多表模型 二.一对多增删改表记录 1.一对多添加记录 2.一对多删除记录 3.一对多修改记录 三.一对 ...

  2. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  3. Django学习——Django测试环境搭建、单表查询关键字、神奇的双下划线查询(范围查询)、图书管理系统表设计、外键字段操作、跨表查询理论、基于对象的跨表查询、基于双下划线的跨表查询

    Django测试环境搭建 ps: 1.pycharm连接数据库都需要提前下载对应的驱动 2.自带的sqlite3对日期格式数据不敏感 如果后续业务需要使用日期辅助筛选数据那么不推荐使用sqlite3 ...

  4. (20)模型层 -ORM之msql 基于双下划线的跨表查询(一对一,一对多,多对多)

    基于对象的跨表查询是子查询 基于双下划线的查询是连表查询 PS:基于双下划线的跨表查询 正向按字段,反向按表名小写 一对一 需求:查询lqz这个人的地址# 正向查询ret = models.Autho ...

  5. Django学习——图书相关表关系建立、基于双下划线的跨表查询、聚合查询、分组查询、F查询、Q查询、admin的使用、使用脚本调用Django、Django查看源生sql

    0 图书相关表关系建立 1.5个表 2.书籍表,作者表,作者详情表(垂直分表),出版社表,书籍和作者表(多对多关系) 一对一 多对多 本质都是一对多 外键关系 3.一对一的关系,关联字段可以写在任意一 ...

  6. Django基础(5) ----基于双下划线的跨表查询,聚合查询,分组查询,F查询,Q查询

    一.基于双下划线的跨表查询 Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系.要做跨关系查询,就使用两个下划线来链接模型(mode ...

  7. django基础之day04,必知必会13条,双下划线查询,字段增删改查,对象的跨表查询,双下划线的跨表查询

    from django.test import TestCase # Create your tests here. import os import sys if __name__ == " ...

  8. Django Mysql数据库-基于双下划线的跨表查询

    一.基于双下划线的跨表查询 Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系.要做跨关系查询,就使用两个下划线来链接模型(mode ...

  9. django orm 基于双下划线的跨表查询

    一..基于双下划线的跨表查询(join实现) key:正向查询按字段,反向查询按表明小写 1.一对多跨表查询 查询在跨表中可以有两种方式,正向查询就是关键字段在你要搜索的表,没有关键字段就是反向查询 ...

随机推荐

  1. 自定义web框架(django)

    Django基础了解知识 HTTP协议(超文本传输协议) HTTP协议 四大特性: 基于TCP/IP之上作用于应用层 基于请求响应 无状态 引申出cookie session token-- 无连接 ...

  2. shell脚本的输入以及脚本拥有特效地输出

    shell脚本的输入以及脚本拥有特效地输出 shell脚本输入之read命令 之前是直接在sh 后加参数 现在是另一种方式 语法:read -参数 -p:给出提示符.默认不支持"\n&quo ...

  3. 文本特征提取---词袋模型,TF-IDF模型,N-gram模型(Text Feature Extraction Bag of Words TF-IDF N-gram )

    假设有一段文本:"I have a cat, his name is Huzihu. Huzihu is really cute and friendly. We are good frie ...

  4. [ Python入门教程 ] Python基础语法

    Python的语法非常简练,因此用Python编写的程序可读性强.容易理解.本章将介绍Python的基本语法和概念. Python文件类型 1.源代码.Python的源代码的扩展名以py结尾,可直接运 ...

  5. WIMBuilder2软件包及精简方案,请把补丁包放到指定位置

    WIMBuilder2软件包及精简方案请把补丁包放到指定位置WimBuilder2-20190901\Projects\WIN10XPE\目录下面精简方案测试适用于LTSB2019.17763.316 ...

  6. [LeetCode] 454. 4Sum II 四数之和之二

    Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such t ...

  7. 端口转发之 lcx

    lcx.exe是一个端口转发工具,有Windows版和Linux版两个版本,Windows版是lcx.exe,Linux版为portmap Windows版使用方法如下: lcx有两大功能: )端口转 ...

  8. python开发--信息处理系统

    #!/usr/bin/python card_list=[] #定义列表变量 def show_menu(): print("*" * 10) print("名片管理系统 ...

  9. OAuth2、OpenID、SMAL 对比

    对比点 OAuth2.0 OpenID SMAL2 票据格式 JSON or SAML2 JSON XML 支持授权 Yes Yes Yes 支持认证 “伪认证” Yes Yes 创建年份 2005 ...

  10. zipfile

    zipfile是一个用于处理zip压缩格式的文件的模块, 主要会用到它的ZipFile类 import zipfile zipfile.is_zipfile('myzip.zip')) # 判断一个文 ...