使用Django为抽象基类设置外键

时间:2008-12-15 04:16:33

标签: python django inheritance django-models

我已经将两个类的公共属性分解为一个抽象基类,但是我有另一个模型需要引用其中一个类。不可能引用ABC,因为它实际上没有数据库表。

以下示例应说明我的问题:

class Answer(models.Model):
    ovramt = models.ForeignKey("Ovramt")
    question = models.ForeignKey("Question")
    answer = models.CharField(max_length=3, choices=(("yes","yes"),("no","no") ("NA","N/A"))
    likelihood = models.IntegerField(choices=LIKELY_CHOICES)
    consequence = models.IntegerField(choices=CONSEQUENCE_CHOICES)

    class Meta:
        abstract = True

class Answer_A(Answer):
    resident = models.ForeignKey("Resident")
    def __unicode__(self):
        return u"%s - %s - %s" %(self.ovramt.ssa.name, self.resident, self.question)    

class Answer_B(Answer):
    def __unicode__(self):
        return u"%s - %s" %(self.ovramt.ssa.name, self.question)    

class Answer_Risk(models.Model):
    answer = models.ForeignKey("Answer")
    risk = models.CharField(max_length=200)

    def __unicode__(self):
        return self.risk

Answer_A和Answer_B略有不同,Answer_A还需要与另一个表的FK关系。 Answer_B以后可能还需要一些特定的属性。如果我将Answer_B作为超类 - 并且有Answer_A子类或组成它,那么问题仍然存在。

无论是Answer_A还是Answer_B,'风险'都是一样的。我还有其他模型需要引用'答案'而不管它的子类型。如何才能做到这一点?你怎么能引用一个类型而不管它的子类型?

更新:
我试图避免加入操作但我不认为我能够。是否值得在所有'答案'中引用'Resident'并在必要时将其归零?或者这被认为是非常糟糕的做法?

2 个答案:

答案 0 :(得分:18)

generic relation似乎是解决方案。但它会使事情进一步复杂化。

在我看来;您的模型结构已经比必要的更复杂。我只想将所有三个Answer模型合并为一个。这样:

  • Answer_Risk无需修改即可使用。
  • 如果resident,您可以将Answer_A设置为无(NULL)。
  • 您可以根据resident == None返回不同的字符串represantations。 (换句话说;相同的功能)

还有一件事;您的答案可能有多种风险吗?如果他们没有或只有一个风险,您应该考虑采用其他实施方式:

我主要关心的是数据库结构和性能(虽然这些更改应该可以提高性能)但代码可维护性

答案 1 :(得分:8)

我的直觉是建议删除基类上的abstract修饰符。你将得到相同的模型结构,但答案将是它自己的表。这样做的缺点是,如果这些是大型表和/或您的查询很复杂,对它的查询可能会明显变慢。

或者,您可以按原样保留模型,但使用GenericForeignKey将ForeignKey替换为Animal。你在模型继承的语法糖中失去了什么,你获得了一点查询速度。

我不相信可以通过ForeignKey(或任何功能相同的)引用抽象基础模型。