ORM中的一对一和多对多

Django ORM 

ORM 一对一

什么时候用一对一?

当 一张表的某一些字段查询的比较频繁,另外一些字段查询的不是特别频繁
把不怎么常用的字段 单独拿出来做成一张表 然后用过一对一关联起来

优势

既保证数据都完整的保存下来,又能保证大部分的检索更快

ORM中的用法

OneToOneField(to="")

示例

在ORM中有作者这个类,类中有一个字段对应作者详情类,作者详情类中包含作者爱好和住址。
类的代码

class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.IntegerField()
books = models.ManyToManyField(to="Book", related_name="authors")
detail = models.OneToOneField(to="AuthorDetail") def __str__(self):
return self.name class AuthorDetail(models.Model):
bobby = models.CharField(max_length=32)
addr = models.CharField(max_length=128)

ORM 多对多的三种方式

方式一:ORM自动创建第三张表

books = models.ManyToManyField(to="Book", related_name="authors")

在 ORM 代码中加上上面那句话,ORM 会自动创建第三张关联 Author 和 Book 的表,自动命名并且自动将字段设置为 author_id 和 book_id 。设置 related_name 是为了方便以后的查询操作。

ORM代码

class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2) publisher = models.ForeignKey(to="Publisher") def __str__(self):
return self.title class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.IntegerField()
books = models.ManyToManyField(to="Book", related_name="books")
detail = models.OneToOneField(to="AuthorDetail") def __str__(self):
return self.name

查询操作

from app01 import models

# 从app01中获取id为1的作者出的书
ret = models.Author.objects.get(id=1).books.all()
print(ret) # 移除作者所写书中id为1的书
models.Author.objects.get(id=1).books.remove(1)
ret = models.Author.objects.get(id=1).books.all()
print(ret)

方式二:自己创建第三张表, 利用外键分别关联作者和书

关联查询比较麻烦,因为没办法使用ORM提供的便利方法

ORM代码

class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2) publisher = models.ForeignKey(to="Publisher") def __str__(self):
return self.title class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.IntegerField()
detail = models.OneToOneField(to="AuthorDetail") def __str__(self):
return self.name # 手动创建第三张作者和书相关联的表
# 此时在ORM层面上,作者和书没有多对多的关系了
class Author2Book(models.Model):
id = models.AutoField(primary_key=True) # 作者id
author = models.ForeignKey(to="Author") # 书id
book = models.ForeignKey(to="Book") # 建立唯一约束
class Meta:
# 顺序不能变
unique_together = ("author", "book")

查询代码

from app02 import models
# 在app02中查询作者id为1的书
ret = models.Author2Book.objects.filter(author_id=1).values_list("book_id") # 1. 得到所对应的书的id
ret = [i[0] for i in ret] # 2. 从book表中将对应id的书取出来
ret = models.Book.objects.filter(id__in=ret)
print(ret)

方式三:自己创建第三张表,使用ORM 的ManyToManyFiled()

使用此种方式创建多对多表的时候,没有 add() remove() 等方法

ORM代码

class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
# 创建外键,关联publish
publisher = models.ForeignKey(to="Publisher") def __str__(self):
return self.title # 作者
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.IntegerField()
# 通过through,through_fields来指定使用我创建的第三张表来构建多对多的关系
books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book",))
# 第一个字段: 多对多设置在哪一张表里, 第三张表通过什么字段找到这张表 就把这个字段写在前面
detail = models.OneToOneField(to="AuthorDetail") def __str__(self):
return self.name # 自己动手 创建作者和书关联的第三张表
# 此时 在ORM层面
class Author2Book(models.Model):
id = models.AutoField(primary_key=True)
# 作者id
author = models.ForeignKey(to="Author")
# 书id
book = models.ForeignKey(to="Book") # memo
memo = models.CharField(max_length=64, null=True) class Meta:
# 建立唯一约束
unique_together = ("author", "book")

查询代码

from app03 import models
# 在app03中查询作者id为1的书
# 操作过程其实跟app01当中的一样
ret = models.Author.objects.get(id=1).books.all()
print(ret)

我们应该用哪种?

1. 如果你第三张表没有额外的字段,就用第一种
2. 如果你第三张表有额外的字段,就用第三种或第一种

ORM中的一对一和多对多的更多相关文章

  1. Django 二——models(admin、ORM),一对一、一对多、多对多操作,all、values、value_list的对比

    内容概要 1.关系对象映射ORM 2.admin的配置(选修) 3.all().values().value_list()的对比 4.数据库操作(一对一.一对多.多对多) 5.HttpResponse ...

  2. Django ORM中常用字段和参数

    一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...

  3. mytabits表关联一对一(多对一?)

    mytabits表关联一对一(多对一?) association联合 联合元素用来处理“一对一”的关系.需要指定映射的Java实体类的属性,属性的javaType(通常MyBatis 自己会识别).对 ...

  4. SQLAlchemy 学习笔记(三):ORM 中的关系构建

    个人笔记,不保证正确. 关系构建:ForeignKey 与 relationship 关系构建的重点,在于搞清楚这两个函数的用法.ForeignKey 的用法已经在 SQL表达式语言 - 表定义中的约 ...

  5. ORM中聚合函数、分组查询、Django开启事务、ORM中常用字段及参数、数据库查询优化

    聚合函数 名称 作用 Max() 最大值 Min() 最小值 Sum() 求和 Count() 计数 Avg() 平均值 关键字: aggregate 聚合查询通常都是配合分组一起使用的 关于数据库的 ...

  6. 2.SSM整合_多表_一对一或多对一的增删改查

    一对一和多对一配置一样,这里就放到一起. 1.配置文件跟上一章一样,这里就不多写了,主要是Mapper映射文件 多 接口 public interface NewsMapper { public vo ...

  7. 第三百零八节,Django框架,models.py模块,数据库操作——链表结构,一对多、一对一、多对多

    第三百零八节,Django框架,models.py模块,数据库操作——链表结构,一对多.一对一.多对多 链表操作 链表,就是一张表的外键字段,连接另外一张表的主键字段 一对多 models.Forei ...

  8. ORM中的N+1问题

    在orm中有一个经典的问题,那就是N+1问题,比如hibernate就有这个问题,这一般都是不可避免的. [N+1问题是怎么出现的] N+1一般出现在一对多查询中,下面以Group和User为例,Gr ...

  9. MySQL基础9-主键约束、外键约束、等值连接查询、一对一和多对多关系

    1.主键约束和外键约束 外键约束 * 外键必须是另一表的主键的值(外键要引用主键!) * 外键可以重复 * 外键可以为空 * 一张表中可以有多个外键! 概念模型在数据库中成为表 数据库表中的多对一关系 ...

随机推荐

  1. 没有Reduce的MapReduce(一)

    尝试了一个没有Reduce的MapReduce. [应用场景]: 从Hbase的A表中进行数据抽样,直接输出到B表中. 这种场景下,相当于只进行了一个数据检索,本来是用Hive就可以实现,但是考虑到业 ...

  2. Matlab中的数据预处理-归一化(mapminmax)与标准化(mapstd)

    一.mapminmax 意思是将矩阵的每一行处理成[-1,1]区间,此时对于模式识别或者其他统计学来说,数据应该是每一列是一个样本,每一行是多个样本的同一维,即对于一个M*N的矩阵来说,样本的维度是M ...

  3. charles4.2下载与破解方法以及配置https.RP

    Charles下载地址 地址:https://www.charlesproxy.com/latest-release/download.do 2. Charles破解 破解地址:https://www ...

  4. 不设置环境变量 直接启动tomcat

    window: 设置 startup.bat set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_144set JRE_HOME=C:\Program Files ...

  5. unity 确定敌人行走路线

    一开始搞这个问题很头疼,无从下手. 1.敌人在随机地点产生后,每个敌人有要有自己自动的行走路线,目的地是保护地,而且行走路线要多样化. 2.敌人在看到玩家时,改变行走路线,向玩家的方向行进,且到了一定 ...

  6. http 错误代码

    2xx  成功  200  正常:请求已完成.  201  正常:紧接 POST 命令.  202  正常:已接受用于处理,但处理尚未完成.  203  正常:部分信息 — 返回的信息只是一部分.   ...

  7. Python之安装第三方扩展库

    PyPI 地址:https://pypi.python.org/pypi 如果你知道你要找的库的名字,那么只需要在右上角搜索栏查找即可. 1.pip安装扩展库 (1)安装最新版本的扩展库: cmd&g ...

  8. MongoDB整理笔记のReplica Sets + Sharding

    MongoDB Auto-Sharding 解决了海量存储和动态扩容的问题,但离实际生产环境所需的高可靠.高可用还有些距离,所以有了"Replica Sets + Sharding" ...

  9. linux权限及目录

    [-][rwx][r-x][r--] r:4 - 读  w:2 - 写  x:1 - 执行 1:代表文件类型 2:代表文件所有者的权限 3:代表文件所在组的权限 4:代表其他用户的权限 chgrp:修 ...

  10. IIS 7.5 使用appliaction Initialization

    https://blogs.msdn.microsoft.com/amol/2013/01/25/application-initialization-ui-for-iis-7-5/ 待续 正在测试 ...