django - 如何在连接表上的两个外键之间强制执行数据库约束?
问题描述
我正在尝试在连接表上的两个外键之间强制执行约束,但我不知道是否可以使用数据库执行此操作,或者是否应该通过我的应用程序或 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 属于同一个 Dataset 的约束。我应该使用数据库还是我的应用程序来执行此操作?或者我应该重新构建我的模型以更轻松地执行此约束?
FWIW,这是一个开源项目,我创建这些表的 PR 在这里:https ://github.com/mapseed/api/pull/161/files如果有帮助,该项目正在使用 Django。
解决方案
在 Django 中“强制”(注意引号)的一种方法是覆盖PlaceTag
'save()
方法。在那里,您可以随时引发异常self.place.dataset != self.tag.dataset
。然而你应该注意到,在某些情况下 Django 不会调用save()
模型的自定义方法:
- 在查询集上调用
update()
方法时。此方法用于批量更新,因此出于性能原因,直接在数据库级别(参考)进行更新。 - 内部(数据)迁移自定义
save()
方法不可用。
在这两种情况下,我提出的方法对强制执行约束没有用(因此开头的引号)。这当然与在数据库级别执行此操作不同,也没有那么强大。无论如何,我认为没有一种可移植的方式(即在任何或大多数 SQL 数据库引擎中都可用)来强制执行这样的条件,因为检查它需要在其他表上进行连接,但我可能在这个问题上错了。
推荐阅读
- c# - 如何将错误气泡消息绑定到 WPF 中的 TextBox?
- python - 0 未在 while 语句中注册为数字
- pandas - 如何按列表中的值对数据框进行排序
- c++ - 哪个版本的 Visual Studio 中引入了函数?
- c# - 未注册 UserIdentity 类型的服务
- javascript - 如何结合范围滑块清空输入字段?
- android - Google Pay API - 在没有 JWT 的情况下向 Google Pay 应用程序插入通行证
- oracle - DENSE_RANK ORDER BY NULL 总是返回 1
- r - 如何使用 R 列出来自 Postgres DB 的表而不是视图?
- javascript - 按月对 SQL 结果进行分组