Django:遵循一对一关系的相反方向

Posted

技术标签:

【中文标题】Django:遵循一对一关系的相反方向【英文标题】:Django: following the reverse direction of the one-to-one relationship 【发布时间】:2011-11-25 01:10:58 【问题描述】:

我对 Django 建模一对一关系的方式有疑问。

假设我们有 2 个模型:A 和 B:

class B(models.Model):
      bAtt = models.CharField()

class A(models.Model):
      b = models.OneToOneField(B)

在创建的表A中,有一个字段“b_id”,但在Django创建的表B中没有“a_id”这样的字段。

因此,给定一个 A 对象,只需通过 A 行的“b_id”列即可检索相应的 B 对象肯定很快。

但是 Django 如何在给定 B 对象的情况下检索 A 对象?

最坏的情况是扫描A表以在“b_id”列中搜索B.id。如果是这样,我们在B模型和表中手动引入一个额外的字段“a_id”是否可取?

提前致谢!

【问题讨论】:

【参考方案1】:

Django 通过 SQL 中的 JOIN 检索字段,有效地将 b_id 与 B.id 匹配的两个表的行融合在一起。

假设您有以下表格:

# Table B
| id | bAtt    |
----------------
|  1 | oh, hi! |
|  2 | hello   |

# Table A
| id | b_id |
-------------
| 3  |  1   |
| 4  |  2   |

然后在B.id = b_id 上的连接将创建以下元组:

| B.id | B.bAtt  | A.id |
------------------------
|  1   | oh, hi! |  3   |
|  2   | hello   |  4   |

无论您从哪一侧输入关系,Django 都会这样做,因此同样有效 :) 数据库实际执行连接的方式取决于数据库实现,但它必须以一种或另一种方式遍历其中的每个元素每个表并比较连接属性。

【讨论】:

别忘了id是有索引的,所以扫描总是很快的。【参考方案2】:

将 id 存储在其中一张表中就足够了。

在情况 1 中,(a.b) 生成的 SQL 将是

SELECT * from B where b.id = a.b_id

在情况 2 中,SQL 将是:

SELECT * from A where a.b_id = b.id

您可以看到两种方式生成的 SQL 都是相似的,并且分别取决于它们的大小。

在几乎所有情况下,索引就足够了,并且只需 1 个 id 就可以实现良好的性能。

【讨论】:

谢谢。这很有帮助,也是我正在寻找的。我也刚刚意识到,即使在给定 A 的情况下,我们马上就有了 b_id,但是要检索整个 B 对象,它仍然需要像相反的情况一样“扫描”。【参考方案3】:

其他对象-关系映射器要求您定义双方的关系。 Django 开发人员认为这是对 DRY(Don't Repeat Yourself)原则的违反,因此 Django 只要求您在一端定义关系。

总是看看doc ;)

【讨论】:

此信息非常有用,感谢 Mansuro。它没有被选作答案,因为它没有直接解决我关于性能的问题。

以上是关于Django:遵循一对一关系的相反方向的主要内容,如果未能解决你的问题,请参考以下文章

django中的一对一的关系

Django 对象扩展/一对一关系问题

Django 无法确定使用一对一关系链接一对多的查询集

Django Admin Cookbook-22如何将一对一关系添加为Admin内联字段

Django模型:同一模型类的对象之间的一对一关系[重复]

Django rest框架一对一关系