一、ORM表和表之间的关系

1、 一对多           --> 外键(ForeignKey)

2、 多对多           --> 另外一张关系表(ManyToManyField)
1. 三种方式
1. 自己建立第三张关系表,外键分别关联两个表
1. 优点
1. 可以扩充第三张关系标的字段
2. 缺点
1. 自己做连表查询
3. 建表例子
class Book(models.Model):
title = models.CharField(max_length=12) class Author(models.Model):
name = models.CharField(max_length=12) # 1. 多对多第一种创建方式:自己创建第三张关系表
class Author2Book(models.Model):
id = models.AutoField(primary_key=True)
author_id = models.ForeignKey(to='Author')
book_id = models.ForeignKey(to='Book')
price = models.IntegerField() # 可以自己扩充需要的字段 2. 通过ORM内置的ManyToManyField,自动创建第三张关系表
1. 优点
1. 提供了很多连表操作的快捷方法--> all(), add(), set(), clear(), remove()
2. 缺点
1. 无法扩展第三张关系表
3. 建表例子
class Book(models.Model):
title = models.CharField(max_length=12) class Author(models.Model):
name = models.CharField(max_length=12)
books = models.ManyToManyField(to='Book') # 字段就这些,无法扩充其他字段 3. 自己创建第三张关系表,通过ManyToManyField关联
1. 优点:
1. 既能够使用多对多查询的快捷方法all()(只能用all,不能使用add,set等),还能够自己扩展第三张关系表的字段
2. 建表例子
class Book(models.Model):
title = models.CharField(max_length=12) class Author(models.Model):
name = models.CharField(max_length=12)
# 告诉ManyToManyField通过(through)Author2Book这张表进行关联,不使用ORM自动创建的第三张表,而是使用我自己创建的表
# through_fields告诉ORM通过哪几个字段进行多对多关联
books = models.ManyToManyField(to='Book', through='Author2Book', through_fields=('author', 'book')) # 1. 多对多第三种创建方式:自己创建第三张关系表,此时外键不需要添加_id了,因为ORM会默认帮你在外键后面加_id
class Author2Book(models.Model):
id = models.AutoField(primary_key=True)
author = models.ForeignKey(to='Author')
book = models.ForeignKey(to='Book')
price = models.IntegerField(null=True) # author_id和book_id要联合唯一
class Meta:
unique_together = (('author', 'book'),)
3. 操作例子
# 多对多的第三张方式也支持all查询
author_obj = Author.objects.first()
# 第一个作者的所有书籍
ret = author_obj.books.all() # 给第一个作者添加一本书
# author_obj.books.add(4) # 报错
Author2Book.objects.create(author_id=1, book_id=4) 2. 以后该用哪种?
1. 当第三张关系表中不需要其他额外字段的时候,我们就用默认ManyToManyField就可以了
2. 当第三张关系表中需要额外的字段时,我们就要用第三种方式,自己建立第三张关系表并且用ManyToManyField关联 3、 一对一 --> OneToOneField(跟ForeignKey一样,生成的字段默认加_id)
0. 用法和外键一样
1. 当一张表里的字段非常多,并且某几个字段的查询频率远远大于其他字段的时候
2. 把常用字段单独拆成一张表,查询的时候更快捷!
3. 当两张表建立了一对一关系后,就不能再关联其他表了
4. 建表例子
class Author(models.Model):
name = models.CharField(max_length=12) # 姓名
gender = models.SmallIntegerField(choices=((1, '男'), (2, '女'), (3, '保密')), default=3) # 性别
phone = models.CharField(max_length=11, unique=True) # 手机
email = models.EmailField() # 邮箱
info = models.OneToOneField(to='AuthorInfo') # 详细信息,一对一,实际数据库的字段是:info_id # 作者详细信息表
class AuthorInfo(models.Model):
birthday = models.DateTimeField() # 生日
city = models.CharField(max_length=12) # 住址
is_marry = models.BooleanField() # 婚否
income = models.BigIntegerField() # 收入 5. 查询例子
# 一对一查询,查询第一个作者的住址
author_obj = Author.objects.first()
ret = author_obj.info.city

二、 ORM关联查询

class Publisher(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
addr = models.TextField()
date = models.DateField() # 成立日期 def __str__(self):
return self.name class Book(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=20)
price = models.DecimalField(max_digits=6, decimal_places=2)
isbn = models.CharField(max_length=20, unique=True) # 书籍的唯一编号
publisher = models.ForeignKey(to='Publisher', on_delete=models.CASCADE) def __str__(self):
return self.title class Author(models.Model):
name = models.CharField(max_length=12) # 姓名
gender = models.SmallIntegerField(choices=((1, '男'), (2, '女'), (3, '保密')), default=3) # 性别
phone = models.CharField(max_length=11, unique=True) # 手机
email = models.EmailField() # 邮箱
books = models.ManyToManyField(to='Book') # 作品
info = models.OneToOneField(to='AuthorInfo') # 详细信息 # 作者详细信息表
class AuthorInfo(models.Model):
birthday = models.DateTimeField() # 生日
city = models.CharField(max_length=12) # 住址
is_marry = models.BooleanField() # 婚否
income = models.BigIntegerField() # 收入

1、 基于对象的查询
1. 正向查
对象.关联字段.属性
# 查询第一本书关联的出版社名称
book_obj = Book.objects.first()
ret = book_obj.publisher.name
print(ret) 2. 反向查
1. 默认不设置related_name属性
1. 查找的对象是多个的时候(一对多或多对多时)
publisher_obj.book_set.all() # 一对多(ForeignKey)和多对多(ManyToManyField)的反向查询:类名_set
publisher_obj.book_set.filter(price__lt=34) 2. 查找的对象时一个的时候(一对一)
author_info_obj.author.name # 一对一(OneToOneField)的反向查询:类名 3. 例如
# 一对多查询(需要给反向查询的表加_set)
# 查询第一本书关联的出版社名称(正向查)
book_obj = Book.objects.first()
ret = book_obj.publisher.name
print(ret) # 查询明哥出版社出版的所有书(反向查)
publisher_obj = Publisher.objects.get(name='明哥出版社')
# 反向查找(多个) .表名_set
ret = publisher_obj.book_set.all()
print(ret) # 一对一查询(不需要给反向查询的表加_set)
# 查询id=1的作者婚否(正向查)
author_obj = Author.objects.first()
ret = author_obj.info.is_marry
print(ret) # 查找住在深圳的那个作者姓名(反向查)
authorinfo_obj = AuthorInfo.objects.get(city='深圳')
ret = authorinfo_obj.author.name
print(ret) 2. 设置related_name='books'属性(publisher = models.ForeignKey(to='Publisher', related_name='books'))
# 查询明哥出版社出版的所有书
publisher_obj = Publisher.objects.get(name='明哥出版社')
publisher_obj.books.all() 2、 使用value基于QuerySet的查询(__表示跨表查询)
1. 正向查
Book.objects.filter(id=1).values_list('publisher__name') 2. 反向查
1. 默认不设置related_name属性,无论一对一、一对多还是多对多默认都用类名的小写
Publisher.objects.filter(id=1).values_list('book__price')
2. 设置related_name='books'属性
Publisher.objects.filter(id=1).values_list('books__price')
3. related_query_name = 'hello'
在关联的字段参数设置了related_query_name = 'hello'后,反向查找就不需要使用表名,而是直接使用"hello" 3. 例子
# 热身:普通的values的使用
# 查询第一本书的名称
ret = Book.objects.filter(id=1).values('title')
print(ret) # 使用:外键基于QuerySet跨表查询
# 查询第一本书关联的出版社名称(__表示跨表查询)(正向查找)
# valuse('publisher')表示通过外键找到了publisher表,__表示跨表取到publisher表的字段的值
ret = Book.objects.filter(id=1).values('publisher__name')
print(ret) # 反向查找
# 查询id=1的出版社的所有书的名称和价格
ret = Publisher.objects.filter(id=1).values_list('book__title', 'book__price')
print(ret) # 一对一基于QuerySet跨表查询
# 查询id=1的作者婚否(正向查找)
ret = Author.objects.filter(id=1).values('info__is_marry')
print(ret) # 查找住在深圳的作者的姓名(反向查找)
ret = AuthorInfo.objects.filter(city='深圳').values('author__name')
print(ret) # 多对多基于QuerySet跨表查询
# 查询id=1的作者关联的所有数据的名称和价格(正向查找)
ret = Author.objects.filter(id=1).values('books__title', 'books__price')
print(ret) # 查找id=1的作者的名字(反向查找)
ret = Book.objects.filter(id=1).values('author__name')
print(ret) # 链式查询
# 查找id=1的书的作者的城市
ret = Book.objects.filter(id=1).values('author__info__city')
print(ret)

ORM关于表那些事的更多相关文章

  1. ORM以及Django使用ORM创建表

    day61 2018-04-28 1. 内容回顾 1. HTTP协议消息的格式: 1. 请求(request) 请求方法 路径 HTTP/1.1\r\n k1:v1\r\n ...\r\n \r\n ...

  2. Django 通过 ORM 实现表的CRUD

    Django 通过 ORM 实现表的CRUD 单表的创建 修改 setting.py 文件 DATABASES = { 'default': { 'ENGINE': 'django.db.backen ...

  3. day59——orm单表操作

    day59 orm单表操作 对象关系映射(object relational mapping) orm语句 -- sql -- 调用pymysql客户端发送sql -- mysql服务端接收到指令并执 ...

  4. python 之 Django框架(orm单表查询、orm多表查询、聚合查询、分组查询、F查询、 Q查询、事务、Django ORM执行原生SQL)

    12.329 orm单表查询 import os if __name__ == '__main__': # 指定当前py脚本需要加载的Django项目配置信息 os.environ.setdefaul ...

  5. 17-2 orm单表操作和多表操作

    参考:https://www.cnblogs.com/liwenzhou/p/8660826.html 一  ORM单表操作 1 增删改查 1. 查询 1. 查所有 models.Publisher. ...

  6. 第十七篇 ORM跨表查询和分组查询---二次剖析

    ORM跨表查询和分组查询---二次剖析 阅读目录(Content) 创建表(建立模型) 基于对象的跨表查询 一对多查询(Publish与Book) 多对多查询 (Author 与 Book) 一对一查 ...

  7. Django ORM多表查询练习

    ORM多表查询 创建表结构: from django.db import models # 创建表结构 # Create your models here. class Class_grade(mod ...

  8. django框架基础-ORM单表操作-长期维护

    ###############    单表操作-添加数据    ################ import os if __name__ == '__main__': os.environ.set ...

  9. ORM单表查询,跨表查询,分组查询

    ORM单表查询,跨表查询,分组查询   单表查询之下划线 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值models ...

随机推荐

  1. CSS3 calc实现滚动条出现页面不跳动

    什么是calc()? calc()从字面我们可以把他理解为一个函数function.其实calc是英文单词calculate(计算)的缩写,是css3的一个新增的功能,用来指定元素的长度.比如说,你可 ...

  2. 左侧固定,右侧自适应的布局方式理解margin负值理论

    一.浮动布局 1.先让固定宽度的div浮动!使其脱离文档流.2.margin-left的值等于固定div的宽度相等. .aside{ float: left; width: 200px; backgr ...

  3. 南京邮电大学java程序设计作业在线编程第七次作业

    王利国的"Java语言程序设计第7次作业(2018)"详细 主页 我的作业列表 作业结果详细 总分:100 选择题得分:60  1. 下列叙述中,错误的是( ). A.Java中, ...

  4. 测者的性能测试手册:Web压力测试工具webbench

    webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装: wget http:/ ...

  5. MySQL MHA FailOver后,原Master节点自动以Slave角色加入解群的研究与实现

    MHA是一套MySQL高可用管理软件,除了检测Master宕机后,提升候选Slave为New Master之外(漂虚拟IP),还会自动让其他Slave与New Master 建立复制关系.MHA Ma ...

  6. PowerDesigner 使用教程(很具体,很实用)

    原文地址为:PowerDesigner 使用教程(很具体,很实用) 1.PowerDesigner 使用教程 从今日开始,每天一部分内容,在每个工作日,争取让大家天天都有的看,每天内容不会太多. 有错 ...

  7. Docker 架构(二)【转】

    Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器. Docker 容器通过 Docker 镜像来创建. 容器与镜像的关系类似于面向对象编程中的对象与类 ...

  8. iOS开发之Swift 4 JSON 解析指南

    Apple 终于在 Swift 4 的 Foundation 的模块中添加了对 JSON 解析的原生支持. 虽然已经有很多第三方类库实现了 JSON 解析,但是能够看到这样一个功能强大.易于使用的官方 ...

  9. Linux学习历程——Centos 7 grep命令

    一.命令简介 grep 命令用于在文本中执行关键词搜索,并显示匹配的结果. 由于grep命令参数很多,这里只列出一些常用的参数. 参数 作用 -b 将可执行文件当作文本文件来搜索 -c 仅显示找到的行 ...

  10. Linux中Zabbix4.0的搭建

    Zabbix简介 Zabbix是一个高度集成的企业级开源网络监控解决方案,与Cacti.nagios类似,提供分布式监控以及集中的web管理界面.zabbix具备常见商业监控软件所具备的功能,例如主机 ...