2017-02-10 118 views
2

我需要Django中的复合外键,这是不受支持的。我可以手动将它添加到数据库,或通过迁移,但它不会反映在模型定义(sadpanda)中。 后端数据库是postgres。Django中的复合外键

这里是我的模型:

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') 

我要上试用表的列trial_id和kit_id(试行及配套的机型)的ID和包ID列ComponentOverride表的外键约束(id是由django自动创建的,模型中的工具包是表中的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; 

我想我需要的是组合键,因为可以有每次试验的多个组件覆盖。

试用版有一个套件,它有很多组件。然而,试用版可能会有一个或多个组件覆盖,这基本上是从套件中取出一个组件,并用另一个替换它。这个模式明确地捕获了替换的信息,也是为什么我不能一起使用唯一。我想确保组件覆盖表中的每个trial_id,kit_id组合都是试用表中的有效组合。

+1

我可以问为什么你认为你需要一个复合键吗?通常的解决方案是使用'unique_together'代替 – Sayse

+1

好问题,我已经编辑了上面的问题来解释。谢谢。 –

回答

0

最后我把这个在我最初的迁移结束:

migrations.RunSQL(""" 
      ALTER TABLE qc_trials_trial 
       ADD CONSTRAINT qc_trials_trial_unique_trial_id_kit_id 
       UNIQUE (id, kit_id); 
      ALTER TABLE qc_trials_componentoverride 
       ADD CONSTRAINT qc_trials_componentoverride_comp_constraint_trial_id_kit_id 
       FOREIGN KEY (kit_id, trial_id) 
       REFERENCES qc_trials_trial(id, kit_id) 
       DEFERRABLE INITIALLY DEFERRED 
"""), 

如果这是我的预期不得不做了很多,我会写一个自定义的操作它。 https://docs.djangoproject.com/en/1.10/ref/migration-operations/#writing-your-own