[基本上,我有一个模型,在该模型中,我创建了许多其他类共享的超类,然后每个这些类具有一些彼此不同的独特功能。假设A类是超类,而B,C和D类是该类的子类。
B类和C类都可以具有D类的倍数,但是我已经看到最好将外键关系放在D类中,然后再将其引用为其父类。现在用其他语言,我可以简单地说它与类A具有ForeignKey关系,然后该语言识别出类的真实类型。但是,我认为这不是Python的工作方式。
推荐此问题的最佳方法是什么?
编辑:这大概是我的意思...
class A(models.Model):
field = models.TextField()
class B(A):
other = <class specific functionality>
class C(A):
other2 = <different functionality>
class D(A):
#I would like class D to have a foreign key to either B or C, but not both.
本质上,B类和C类都具有多个D类。但是特定的D类仅属于其中一个。
例如,如果您要构建一个“地方”的数据库,您将建立非常标准的东西,例如地址,数据库中的电话号码等。然后,如果您想建立一个顶部的餐厅数据库的地方,而不是重复自己并将这些字段复制到餐厅模型,您可以制作餐厅有一个OneToOneField地点(因为餐厅“是”地点;实际上,要解决这个问题通常使用继承,涉及隐式一对一关系)。
通常,您只需要Restaurant
继承自Place
。可悲的是,您需要我认为是hack的东西:从子类到超类(Restaurant
至Place
)进行一对一引用
您也可以进行一般关系http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1,并在设置或保存时检查类型以将其限制为B或C。这可能比找出直接参考要花的功夫更多,但可能会感觉更干净。
执行此操作的一种方法是如下添加中间类:
class A(Model):
class Meta(Model.Meta):
abstract = True
# common definitions here
class Target(A):
# this is the target for links from D - you then need to access the
# subclass through ".b" or ".c"
# (no fields here)
class B(Target):
# additional fields here
class C(Target):
# additional fields here
class D(A):
b_or_c = ForeignKey(Target)
def resolve_target(self):
# this does the work for you in testing for whether it is linked
# to a b or c instance
try:
return self.b_or_c.b
except B.DoesNotExist:
return self.b_or_c.c
使用中间类(目标)可以保证从D到B或C只有一个链接。这有意义吗?有关更多信息,请参见model inheritance。
在您的数据库中,将存在用于Target,B,C和D的表,但没有用于A的表,因为它被标记为抽象(相反,与A上的属性相关的列将出现在Target和D中)。
[警告:我实际上没有尝试过此代码-欢迎任何更正!]
我在这里看到问题:
class D(A):
#D has foreign key to either B or C, but not both.
无法做到。您必须同时添加两者,因为必须在SQL列中准确定义。
而且,即使像您这样的继承模型都可以使用syncdb
进行编译-它们的行为似乎并不像您期望的那样-至少我无法使它们工作。我无法解释原因。
这是FK在Django中的工作方式
class A(models.Model):
a = models.CharField(max_length=5)
class B(models.Model):
a = model.ForeignKey(A, related_name='A')
b = models.CharField(max_length=5)
class D(models.Model):
a = model.ForeignKey(A, related_name='A')
parent = model.ForeignKey(B, related_name='D')
这样,您可以有效地使B中具有D的倍数。
模型中的继承(例如B(A)类)无法正常工作。也许其他人可以更好地解释它。
看this doc页面。这与Django中的多对一关系有关。
b = B()
b.D_set.create(...)