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. ChainOfResponsibilityPattern(23种设计模式之一)

    参考书籍:设计模式-可复用面向对象软件基础(黑皮书) 目的:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿这条链传递该请求,直到有一个对象处理它为止 ...

  2. Openssl rsautl命令

    一.简介 rsautl指令能够使用RSA算法签名,验证身份,加密/解密数据 二.语法 openssl rsautl [-in file] [-out file] [-inkey file] [-pas ...

  3. Ubuntu 安装QT5 后编译程序报错: FindQt5Widgets.cmake

    安装QT5.4后,需要编译一个C++程序. Cmakelist 有find_package(Qt5Widgets REQUIRED),cmake 报错如下: CMake Error at CMakeL ...

  4. [Training Video - 3] [Groovy in Detail] Non-static and Static variables, objects and object referances

    log.info "starting" // we use class to create objects of a class Planet p1 = new Planet() ...

  5. python 中面向对象编程简单总结1

    1.类的定义方式 class ClassName(object): #object 表示继承的类,默认为object pass 类的使用类似函数的调用,也可以认为是调用了一次模板来创建一个实例. 2. ...

  6. python report中文显示乱码

    环境:python2.7 测试框架: nose (1.3.7) nose-html-reporting (0.2.3) 问题:生成测试报告失败的时候,报告会抓取代码中的print,打开后看到的中文是乱 ...

  7. SVN错误:Attempted to lock an already-locked dir及不能提交.so文件

    当使用svn提交代码时,如果中断提交,就会进入工作拷贝的锁定状态. 这是需要用svn cleanup上次关闭时的锁定 如果没有Tortises,则直接进入到上面的文件夹下的.svn目录,删除lock文 ...

  8. 【重要】拷贝NIOS II工程后,修改工程前必须要做的10件事

    1.拷贝现有工程到新的目录2.打开Quartus II工程文件3.打开NIOS II EDS软件4.切换工作空间到当前的新工程根目录5.在NIOS II EDS软件中将已有的软件工程先删除掉(不要勾选 ...

  9. [修正] Firemonkey 中英文混排折行,省略字符,首字避开标点

    问题:FMX 在移动平台的文字显示并非由该平台的原生 API 来显示,而是由 FMX.TextLayout.GPU 来处理,也许是官方没留意到中文字符的问题,造成在中英文混排折行时,有些问题. 修正: ...

  10. Android-自定义IntentSession来传递数据

    在上一篇博客中介绍到,Android-Intent意图传递数据,能够传递基本数据类型系列,能够传递对象(需要序列化),等操作: 但是如果要传递 List<T>,这种类型的数据,就不能通过I ...