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. LoadRunner11学习记录二 -- 进行cookie模拟

    1.LoadRunner录制打开一个网页的脚本,会生成脚本夹杂迅雷,迅雷看看,百度等链接地址,这是因为ie打开之后会加载未禁用的加载项.需要把相关的加载项禁用掉. 禁用ie加载项步骤,工具--管理加载 ...

  2. cJSON结构体构建

    cJSON结构体构建 一:cJSON的构建. int create_objects() { cJSON *root, *fmt, *img, *thm, *fld; char *out; int i; ...

  3. idea 删除代码的注释

      搜索栏使用 正则表达式搜索 (/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/|[ \t]*//.*)   会搜索出来所有注释的代码 用空格replace替换掉就 ...

  4. mybatis 传参是 list<string> 的注意事项

    <!--付款 批量 修改账单状态--><update id="editbillpayALL" parameterType="java.util.List ...

  5. 【转载】redis优化配置和redis.conf说明

    转载地址:http://blog.csdn.net/luozhonghua2014/article/details/40568707?utm_source=tuicool&utm_medium ...

  6. HDU 6153 A Secret (KMP)

    题意:给定两个串,求其中一个串 s 的每个后缀在另一个串 t 中出现的次数. 析:首先先把两个串进行反转,这样后缀就成了前缀.然后求出 s 的失配函数,然后在 t 上跑一遍,如果发现不匹配了或者是已经 ...

  7. Samba文件服务器安装配置

    很久都没有更新博客了,人要学好难,跟着学坏容易,这个其实是我一直以来不明白的地方.如果,能反过来,应该是很多人求之不得的美事吧.说远了,我就是这种一放松下来,就容易堕落的一份子. 最近也是工作的原因, ...

  8. Delphi 10.1.2 berlin开发跨平台APP的几点经验

    1.ios不允许app有退出功能,所以不能调用Application.Terminate. 2.info.plist文件的自定义:info.plist文件是由info.plist.TemplateiO ...

  9. DELPHI XE5-8 弹出列表框供选择

    点击章节练习: var tmplm:Tlistboxitem; begin dm.FDQTMP.SQL.Clear; dm.FDQTMP.SQL.Add('select GSESSON from TS ...

  10. 构建基于asp.net core 的docker应用并发布

    发布Docker镜像的方法有很多种,asp.net core的发布需要在windows系统中 开门见山,首先保证已经在Centos上安装好了Docker.创建一个asp.net core的webapi ...