我需要 Django 中的复合外键,但不受支持。我可以将它手动添加到数据库中,或通过迁移添加,但它不会反射(reflect)在模型定义 (sadpanda) 中。 后端数据库是 postgres。
这是我的模型:
class Trial(models.Model):
kit = models.ForeignKey(to='Kit')
class Kit(models.Model):
name = models.CharField(max_length=500)
class Component(models.Model):
kit = models.ForeignKey(null=True, blank=True, to='Kit', related_name='components')
class ComponentOverride(models.Model):
trial = models.ForeignKey(to='Trial')
kit = models.ForeignKey(to='Kit')
component_to_replace = models.ForeignKey(to='Component', related_name='replaced')
component_replace_with = models.ForeignKey(to='Component', related_name='replaced_with')
我想在 ComponentOverride 表的 trial_id 和 kit_id 列(模型中的 trial 和 kit)的外键约束到 trial 表上的 id 和 kit id 列(id 由 django 自动创建,模型中的 kit是表格中的 kit_id)。
基本上我想要一个等同于:
ALTER TABLE app_label_trial
ADD CONSTRAINT app_label_trial_unique_trial_id_kit_id
UNIQUE (id, kit_id);
ALTER TABLE app_label_componentoverride
ADD CONSTRAINT app_label_componentoverride_comp_constraint_trial_id_kit_id
FOREIGN KEY (kit_id, trial_id)
REFERENCES app_label_trial(id, kit_id)
DEFERRABLE INITIALLY DEFERRED;
我认为我需要组合键,因为每次试验可以覆盖多个组件。
一个试用版有一个套件,其中包含许多组件。然而,试验可能有一个或多个组件覆盖,这实际上是从套件中取出一个组件并用另一个组件替换它。这个模式明确地捕获了那个替换的信息,这就是为什么我不能同时使用 unique 的原因。我想确保 componentoverride 表中的每个 trial_id、kit_id 组合在 trial 表中都是有效组合。
最佳答案
针对上述情况的简单解决方案是从 ComponentOverride
中省略 kit
。如果您从 ComponentOverride
引用 Trial
,则您通过 trial__kit_id
隐式引用了试用套件。通过在 ComponentOverride
中另外保存 kit_id
,您将不必要地复制数据。通过不保存相同的数据两次,约束问题就会自行消失。
(这是一个老问题,但吸引人的标题仍然为它引来了一些流量,所以也许上面的内容可以让一些人在不需要的时候免于陷入复合外键的困境。)
关于python - Django 中的复合外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42165838/