一、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. 点击checkbox后,$(this).attr('checked')得到的值不会发生改变

    这两天遇到一个问题,就是在点击checkbox后,$(this).attr('checked')得到的值要么是undefined,要么是checked,同一个表单一直点击却一点都不会发生改变,调试了一 ...

  2. canvas 时钟动画

    平时在公司不忙的时候,就喜欢写一些小效果什么的,一来复习复习,二来可以发现一些问题. 今天在群里看别人发了一手表的图片,卧槽...妥妥的工作好多年的节奏,后来想想还是做好自己的事情算了,想那多干啥,就 ...

  3. Netty学习笔记(四) 简单的聊天室功能之服务端开发

    前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...

  4. Python第三天 序列 5种数据类型 数值 字符串 列表 元组 字典 各种数据类型的的xx重写xx表达式

    Python第三天 序列  5种数据类型  数值  字符串  列表  元组  字典 各种数据类型的的xx重写xx表达式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell ...

  5. 网络编程中TCP基础巩固以及Linux打开的文件过多文件句柄的总结

    1.TCP连接(短链接和长连接) 什么是TCP连接?TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议. 当网络通信 ...

  6. 本地系统服务例程:Nt和Zw系列函数

    Windows本地操作系统服务API由一系列以Nt或Zw为前缀的函数实现的,这些函数以内核模式运行,内核驱动可以直接调用这些函数,而用户层程序只能通过系统进行调用.通常情况下用户层应用程序不会直接调用 ...

  7. LeetCode算法题-Merge Two Binary Trees(Java实现)

    这是悦乐书的第274次更新,第290篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第142题(顺位题号是617).提供两个二叉树,将其合并为新的二叉树,也可以在其中一个二 ...

  8. 我的第一个python web开发框架(26)——定制ORM(二)

    弄完底层数据库操作模块后,接下来要做的是ORM的正式设计.在开始之前,我们需要思考一下怎么来设计一个ORM呢?这个类它能帮助我们处理什么样的问题?需要有哪些功能模块?怎么做到针对不同的数据库与表单进行 ...

  9. C#中@的作用

    1.在书写文件路径时,消除"/"的转义功能 string FileDirect = "C:\Text\Debug\Text.txt"; \\编译会报错 stri ...

  10. 爬虫系列----scrapy爬取网页初始

    一 基本流程 创建工程,工程名称为(cmd):firstblood: scrapy startproject firstblood 进入工程目录中(cmd):cd :./firstblood 创建爬虫 ...