python 使用 Django 为抽象基类设置外键
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/367461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting up a foreign key to an abstract base class with Django
提问by Josh Smeaton
I've factored out common attributes from two classes into an abstract base class, however I have another model that needs to reference either one of those classes. It's not possible to reference an ABC as it doesn't actually have a database table.
我已经将两个类的公共属性分解为一个抽象基类,但是我有另一个模型需要引用这些类中的任何一个。无法引用 ABC,因为它实际上没有数据库表。
The following example should illustrate my problem:
下面的例子应该说明我的问题:
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 and Answer_B are slightly different in that Answer_A also needs a FK relationship to another table. Answer_B may also require some specific attributes later. The problem would STILL exist if I had Answer_B be the superclass - and have Answer_A subclass or compose it.
Answer_A 和 Answer_B 略有不同,Answer_A 还需要与另一个表的 FK 关系。稍后,Answer_B 可能还需要一些特定的属性。如果我让 Answer_B 成为超类,并且拥有 Answer_A 子类或组合它,问题仍然存在。
A 'Risk' is the same whether it's Answer_A or Answer_B. I also have other models that need to reference an 'Answer' regardless of it's sub-type. How can this be done? How can you reference a type regardless of it's sub-type?
无论是 Answer_A 还是 Answer_B,“风险”都是相同的。我还有其他模型需要引用“答案”,而不管它是什么子类型。如何才能做到这一点?你如何引用一个类型而不考虑它的子类型?
Update:
I was trying to avoid a join operation but I don't think I'm going to be able to. Would it be worth having the reference to 'Resident' in all 'Answer's and just nulling it where required? Or is that considered very bad practice?
更新:
我试图避免加入操作,但我认为我无法做到。是否值得在所有“答案”中提及“居民”并在需要时将其归零?或者这被认为是非常糟糕的做法?
采纳答案by muhuk
A generic relationseems to be the solution. But it will complicate things even further.
一个通用的关系似乎是解决方案。但这会使事情进一步复杂化。
It seems to me; your model structure is already more complex than necessary. I would simply merge all three Answer
models into one. This way:
在我看来; 您的模型结构已经比必要的复杂。我会简单地将所有三个Answer
模型合并为一个。这条路:
Answer_Risk
would work without modification.- You can set
resident
to None (NULL) in case of anAnswer_A
. - You can return different string represantations depending on
resident == None
. (in other words; same functionality)
Answer_Risk
无需修改即可工作。- 您可以设置
resident
为 None (NULL) 在Answer_A
. - 您可以根据
resident == None
. (换句话说;相同的功能)
One more thing; are your answers likely to have more than one risk? If they'll have none or one risk you should consider following alternative implementations:
还有一件事; 您的答案是否可能有不止一种风险?如果他们没有或只有一个风险,您应该考虑以下替代实现:
- Using a one-to-one relationship
- Demoting risk as a field (or any number of fields) inside
Answer
class.
- 使用一对一关系
- 将风险降级为类内的一个字段(或任意数量的字段)
Answer
。
My main concern is neither database structure nor performance (although these changes should improve performance) but code maintainability.
我主要关心的既不是数据库结构也不是性能(尽管这些更改应该会提高性能),而是代码可维护性。
回答by Daniel Naab
My gut would be to suggest removing the abstract modifier on the base class. You'll get the same model structure, but Answer will be it's own table. The downside of this is that if these are large tables and/or your queries are complex, queries against it could be noticeably slower.
我的直觉是建议删除基类上的抽象修饰符。您将获得相同的模型结构,但答案将是它自己的表。这样做的缺点是,如果这些是大表和/或您的查询很复杂,则针对它的查询可能会明显变慢。
Alternatively, you could keep your models as is, but replace the ForeignKey to Answer with a GenericForeignKey. What you lose in the syntactic sugar of model inheritance, you gain a bit in query speed.
或者,你可以保留你的模型为是,但更换ForeignKey的一个来回答GenericForeignKey。你在模型继承的语法糖中失去了什么,你在查询速度上获得了一点。
I don't believe it's possible to reference an abstract base model by ForeignKey (or anything functionally the same).
我不相信可以通过 ForeignKey(或任何功能相同的东西)引用抽象基本模型。