32

我已经将两个类的公共属性分解为一个抽象基类,但是我有另一个模型需要引用这些类中的任何一个。不可能引用 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,“风险”都是相同的。我还有其他模型需要引用“答案”,无论其子类型如何。如何才能做到这一点?不管它的子类型如何,你如何引用一个类型?

更新:
我试图避免加入操作,但我认为我做不到。是否值得在所有“答案”中引用“居民”并在需要时将其取消?或者这被认为是非常糟糕的做法?

4

2 回答 2

18

通用关系似乎是解决方案。但这会使事情变得更加复杂。

在我看来; 您的模型结构已经比必要的复杂。我会简单地将所有三个Answer模型合并为一个。这边走:

  • Answer_Risk无需修改即可工作。
  • residentAnswer_A. _
  • 您可以根据resident == None. (换句话说;相同的功能)

还有一件事; 你的答案可能有不止一种风险吗?如果他们没有风险或只有一种风险,您应该考虑以下替代实现:

  • 使用一对一的关系
  • 将风险降级为类内的一个字段(或任意数量的字段)Answer

我主要关心的既不是数据库结构也不是性能(尽管这些更改应该会提高性能),而是代码的可维护性

于 2008-12-15T08:24:54.443 回答
8

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

或者,您可以保持模型不变,但将 ForeignKey to Answer 替换为GenericForeignKey。你在模型继承的语法糖中失去了什么,你在查询速度上获得了一点。

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

于 2008-12-15T04:33:46.470 回答