ORM中的一对一和多对多

Django ORM 

ORM 一对一

什么时候用一对一?

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

优势

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

ORM中的用法

OneToOneField(to="")

示例

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

  1. class Author(models.Model):
  2. name = models.CharField(max_length=32)
  3. age = models.IntegerField()
  4. phone = models.IntegerField()
  5. books = models.ManyToManyField(to="Book", related_name="authors")
  6. detail = models.OneToOneField(to="AuthorDetail")
  7. def __str__(self):
  8. return self.name
  9. class AuthorDetail(models.Model):
  10. bobby = models.CharField(max_length=32)
  11. 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代码

  1. class Book(models.Model):
  2. title = models.CharField(max_length=32)
  3. publish_date = models.DateField(auto_now_add=True)
  4. price = models.DecimalField(max_digits=5, decimal_places=2)
  5. publisher = models.ForeignKey(to="Publisher")
  6. def __str__(self):
  7. return self.title
  8. class Author(models.Model):
  9. name = models.CharField(max_length=32)
  10. age = models.IntegerField()
  11. phone = models.IntegerField()
  12. books = models.ManyToManyField(to="Book", related_name="books")
  13. detail = models.OneToOneField(to="AuthorDetail")
  14. def __str__(self):
  15. return self.name

查询操作

  1. from app01 import models
  2. # 从app01中获取id为1的作者出的书
  3. ret = models.Author.objects.get(id=1).books.all()
  4. print(ret)
  5. # 移除作者所写书中id为1的书
  6. models.Author.objects.get(id=1).books.remove(1)
  7. ret = models.Author.objects.get(id=1).books.all()
  8. print(ret)

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

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

ORM代码

  1. class Book(models.Model):
  2. title = models.CharField(max_length=32)
  3. publish_date = models.DateField(auto_now_add=True)
  4. price = models.DecimalField(max_digits=5, decimal_places=2)
  5. publisher = models.ForeignKey(to="Publisher")
  6. def __str__(self):
  7. return self.title
  8. class Author(models.Model):
  9. name = models.CharField(max_length=32)
  10. age = models.IntegerField()
  11. phone = models.IntegerField()
  12. detail = models.OneToOneField(to="AuthorDetail")
  13. def __str__(self):
  14. return self.name
  15. # 手动创建第三张作者和书相关联的表
  16. # 此时在ORM层面上,作者和书没有多对多的关系了
  17. class Author2Book(models.Model):
  18. id = models.AutoField(primary_key=True)
  19. # 作者id
  20. author = models.ForeignKey(to="Author")
  21. # 书id
  22. book = models.ForeignKey(to="Book")
  23. # 建立唯一约束
  24. class Meta:
  25. # 顺序不能变
  26. unique_together = ("author", "book")

查询代码

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

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

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

ORM代码

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

查询代码

  1. from app03 import models
  2. # 在app03中查询作者id为1的书
  3. # 操作过程其实跟app01当中的一样
  4. ret = models.Author.objects.get(id=1).books.all()
  5. 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. code1319 玩具装箱

    一个划分dp,不过由于划分个数任意,仅用一维数组就可以 设dp[i]表示前i个装箱(任意个箱子)的费用最小值 dp[i]=min(dp[u]+cost(u+1,i)) 但是n<=50000,n方 ...

  2. Django中的元类-乾颐堂

    看Django(1.6)的Form相关源代码时比较迷惑,于是节选了django.forms.forms.py中的几个代码片段来分析Django中是怎么使用元类的: 1 2 3 4 5 6 7 8 9 ...

  3. shared_ptr / weak_ptr 代码片段

    参考<<Boost程序库完全开放指南>> shared_ptr  类摘要(只列出了常用的部分)和相关说明 template <class T> class shar ...

  4. 我的ubuntu14.04配置

    完全卸载java(移除所有 Java相关包 (Sun, Oracle, OpenJDK, IcedTea plugins, GIJ)) 转载修改, 原文见:http://blog.csdn.net/s ...

  5. mongodb ---- findAndModify 写法

    db.coll.findAndModify({ query:{x:"ggg"}, update:{$set:{"x":"gggg"}}, f ...

  6. BZOJ 2243 染色 (线段树+树链剖分)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9895  Solved: 3735[Submit][Status ...

  7. LinqPad介绍,下载,用法说明

    介绍一款用于Linq运算和测试的工具,LinqPad.我感觉这个工具非常优秀,不只是功能上优秀,在使用上也非常优秀,让我爱不释手. LinqPad官方地址:http://www.linqpad.net ...

  8. MyBatis和Hibernate相比较

    作者:乌拉拉链接:http://www.zhihu.com/question/21104468/answer/58579295 1.开发对比开发速度 Hibernate的真正掌握要比Mybatis来得 ...

  9. 探索式软件测试—Exploratory Software Testing

    最近找到去年上半年看过一本关于测试方面书籍的总结笔记,一直放在我的个人U盘里,当时是用Xmind记录的,现在重新整理下分享给大家了! James A.Whittaker [美] 詹姆斯·惠特克(软件测 ...

  10. Grails项目开发——前端请求跨域问题

    Grails项目开发--前端请求跨域问题 最近做项目采用前后端分离的思想,使用Grails作为后台开发Restful API供前端调用. 在项目开发的过程中,遇到前端没办法通过ajax访问到后台接口的 ...