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. EZOJ #227

    传送门 分析 我们发现第一段数和最后一段数对答案的贡献系数为1/-1,其余为0/2/-2 而且对于相邻两段不能系数均非0 于是可以dp 代码 #include<iostream> #inc ...

  2. array_combine()

  3. jenkins+maven+svn实现简单的一键发布

    前言      在安装之前,我想说明一下本文的目的,jenkins的一款持续集成工具,      它可以做的事情很多,其中一个主要的功能就是简化部署流程          回想一下我们的发布流程:   ...

  4. boost::bind和boost::function使用示例

    C++11已支持bind和function,之前的不支持,但可以借助boost达到同样目的.看如下两段代码: 1) 创建HDFS目录 void hdfs::init() { if (0 == hdfs ...

  5. 实用的chrome插件

      有人说Chrome是世界上最好的浏览器,当然也会有不赞同.但不论怎样,工具而已,何必限制,任何一个用好了都能迅速提高我们的效率,不过还是推荐Chrome. 自然问题就变成:“为什么要用Chrome ...

  6. 2、Semantic-UI之网格布局

    2.1 网格布局   在semantic-ui中提供了16个网格,使用class="column",当然也可以通过数字来表示当前网格大小.   在Semantic-UI中定义的网格 ...

  7. 买了个vultr的vps,准备把博客转过去,顺便记录一点操作。

    1.shadow影子socks梯子已经搭好了,步骤: apt-get install python-pip pip install shadowsocks 任意目录创建配置文件json(ss可以在很多 ...

  8. delphi 中封装的VCl窗体Tab键响应问题

    在DLL中的子窗体不会响应Tab按键的,这个时候就需要手动去指定Tab键的操作,但是前提是主窗体要向这个窗体发送一个消息,一个Tab键按下的消息.基本顺序是这样的: 1. 主窗体用Hook技术捕获Ta ...

  9. XE5安卓手机要求

    1 ARMv7 的 CPU v6 的肯定不支持.2 黑屏是因为你的手机 CPU 不支持 NEON 特性.或者是 T2 CPU.3 系统版本  2.3.3 到 2.3.9 或者 4.0 以上.4. SD ...

  10. var 在linq中的使用

    一:掌握linq,写出超炫的代码 1. var关键字 [隐式类型] 隐式类型 和 匿名类型的不同叫法. 特性 和 属性 2.隐式类型 就是让编译器来推断的一种语法糖. 二:隐式类型的应用场景 1. 简 ...