如何在联接表上的两个外键之间强制执行数据库约束?

时间:2019-01-17 21:57:27

标签: django database django-models orm model

我试图在联接表上的两个外键之间强制执行约束,但我不知道是否可以使用数据库来完成约束,还是应该通过应用程序或ORM来实现约束。

这是我的桌子:

Dataset

Tag
 - Dataset: FK
 - name: string (eg: "park", "church", etc)

Place
 - Dataset: FK
 - latitude
 - longitude

PlaceTag (my join table)
 - Tag: FK
 - Place: FK
 - note: string (eg: "this place is my favorite park")

我要强制执行以下约束:每个PlaceTag都有一个Tag和一个Place,它们属于同一个数据集。我应该使用数据库还是我的应用程序执行此操作?还是应该重新构建模型以更轻松地实施此约束?

FWIW,这是一个开源项目,我在这里创建这些表的PR位于:https://github.com/mapseed/api/pull/161/files该项目正在使用Django,如果有帮助的话。

1 个答案:

答案 0 :(得分:1)

在Django中“执行”(注意引号)的一种方法是重写PlaceTag的{​​{1}}方法。每当save()时,您都可以在其中引发异常。但您应该注意,在某些情况下Django不会调用模型的自定义self.place.dataset != self.tag.dataset方法:

  1. 在查询集上调用save()方法时。此方法用于批量更新,因此出于性能考虑,直接在数据库级别(reference)进行更新。
  2. 内部(数据)迁移自定义update()方法不可用。

在这两种情况下,我建议的方法对于强制执行约束将无济于事(因此,引号在开头)。当然这是不一样的,并且不如在数据库级别上强制执行那样强。无论如何,我认为没有一种可移植的方式(即在任何或大多数SQL数据库引擎中都可以使用)强制执行这种条件,因为检查该条件将需要在其他表上进行联接,但是我对此可能是错误的。