基本上,我有一个模型,我创建了一个许多其他类共享的超类,然后每个类都有一些彼此不同的独特功能。假设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类只属于其中一个。
答案 0 :(得分:3)
来自Django Docs:
例如,如果您正在构建一个 你会建立的“地方”数据库 非常标准的东西,如地址, 数据库中的电话号码等。 然后,如果你想建立一个 顶部的餐馆数据库 地方,而不是重复自己 并复制那些领域 餐厅模特,你可以做 餐厅有OneToOneField 地方(因为餐厅“是一个” 地点;事实上,要处理这个你 通常使用继承,其中 涉及隐含的一对一 关系)。
通常情况下,您只需Restaurant
继承Place
。遗憾的是,你需要我认为是黑客攻击:从子类到超类(Restaurant
到Place
)进行一对一的引用
答案 1 :(得分:3)
您还可以执行通用关系http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1,并在设置或保存时检查类型以将其约束为B或C.这可能比确定直接参考更有用,但可能会感觉更清洁。
答案 2 :(得分:3)
一种方法是按如下方式添加中间类:
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
使用中间类(Target)可以保证只有一条从D到B或C的链接。这有意义吗?有关详细信息,请参阅http://docs.djangoproject.com/en/1.2/topics/db/models/#model-inheritance。
在你的数据库中会有Target,B,C和D的表,但不是A,因为它被标记为抽象(相反,与A上的属性相关的列将出现在Target和D中)。
[警告:我实际上没有尝试过此代码 - 欢迎任何更正!]
答案 3 :(得分:2)
我在这里看到一个问题:
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(...)