2009-07-11 116 views
10

基本上,我有一个模型,我创建了许多其他类共享的超类,然后每个类都有一些彼此不同的独特功能。假设类A是超类,而类B,C和D是该类的子类。Django模型继承和外键

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

你能解释为什么你需要继承吗? – Evgeny 2009-07-11 22:25:56

+0

有一个相关的问题有一些很好的答案,这可能有助于:https://stackoverflow.com/questions/1114767/django-model-inheritance-and-foreign-keys – Miranda 2017-12-07 07:28:36

回答

3

Django Docs

例如,如果你正在建设一个 数据库的“场所”,你将建立 非常标准的东西,如地址, 电话号码等在数据库。 然后,如果你想建立的 地方顶部的 数据库的餐馆,而不是重复自己 并在 餐厅模型复制这些领域,你可以做 餐厅有OneToOneField到 地方(因为餐厅“是一个” 的地方;实际上,为了处理这个问题,你通常会使用继承,其中 涉及隐式的一对一关系)。

通常情况下,您将只有Restaurant继承自Place。可悲的是,你需要什么,我认为一个黑客:从子做出一个对一个参考进行超(RestaurantPlace

+0

是不是django默认提供这种一对一的引用?例如对于多表继承模型,“restaurant.place”返回Place的相应实例,而不需要用户定义除继承之外的任何关系。 – 2012-01-26 14:19:13

1

我看到这里有一个问题:

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') 

这种方式可以有效地具有d的倍数B.

在模型继承(如B类(A))不为工作我会期待它。也许别人可以更好地解释它。

看看this doc页面。这是关于Django的多对一关系。

b = B() 
b.D_set.create(...) 
+0

我的问题是,我想类d属于无论是A类还是B类,而不是两者。我会在我的问题中澄清。 – AlbertoPL 2009-07-11 22:59:24

1

的一种方法是如下添加一个中间类:

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.这是否合理?有关更多信息,请参阅http://docs.djangoproject.com/en/1.2/topics/db/models/#model-inheritance

在你的数据库将有目标,B,C和d表,但不是一个,因为被标记为抽象的(相反,与上一个属性栏将出现在目标和d)。

[警告:我实际上没有试过这个代码 - 任何更正欢迎!]