【问题标题】:Tricky model inheritance - Django棘手的模型继承 - Django
【发布时间】:2011-01-30 04:24:30
【问题描述】:

我认为这有点棘手,至少对我来说是这样。 :)

所以我有 4 个模型 PersonSingerBassistNinja

歌手、贝斯手和忍者继承自 Person。


问题是每个 Person 都可以是它的任何子类。

例如一个人可以是歌手也可以是忍者。另一个人可以是贝斯手和忍者。另一个可以是全部三个。

我应该如何组织我的模型?


我们将不胜感激!

【问题讨论】:

  • 你在做什么样的项目??这听起来棒极了!我想成为一个贝斯手忍者混乱/邪恶。
  • 有一次我有个朋友玩吟游诗人。他死了,换了心脏,变得邪恶(不要问)。起死回生后,他扔掉了琵琶,拿起了一把电吉他(再说一遍,别问了),鼓起勇气用他的刀拨弦,同时做金属咕噜声。显然,这很棒。
  • +1 忍者贝斯手...

标签: python django inheritance django-models django-orm


【解决方案1】:

你可以让你所有的职业(忍者,贝斯手......)继承自模型中的Person,然后在后端代码中使用函数isinstance区分个人的职业。

【讨论】:

    【解决方案2】:

    原则上您可以执行以下操作:

    class Role(models.Model):       
         ......
    
    class Ninja(Role):
         .......
    
    class Person(models.Model):
          roles = models.ManyToManyField(Role)
    

    但是你遇到了 Person.roles.objects.all() 只能给你 Role 实例的问题。因此,您需要一种方法将 Role 的每个实例转换为合适的子类,例如 Ninja 或 Pirate。这是讨论此问题的线程的链接。

    http://groups.google.com/group/django-users/browse_thread/thread/f4241bc16455f92d/7268c3f7bca6b046

    总之,Alex 和 Stefano 给出了比我更有用的答案。

    【讨论】:

      【解决方案3】:

      我同意 Alex 所描述的角色解决方案。你所拥有的不是不同的人的子类。一个人可以扮演不同的角色。

      但我听到你说:“嘿,忍者可以有一个属性“numberOfStars”,而歌手可以有一个属性“highestNote”。接口相同:忍者可以有方法 throwStar() 并消失(),而歌手可以有 sing() 和 getWasted(),贝斯手可以有 goFunky() 和 slapPop()

      您的数据模型需要一个非常松散的架构。如此松散,事实上,您根本没有架构。如果歌手决定使用贝斯并即兴创作曲子,那很好。如果他想扮演忍者,你调用 throwStar 会返回错误,因为他没有星星,但原则上你可以给歌手分配星星,让他扔星星。

      您所涉足的是本体世界,而不是模式。你有一个资源,它是“某物”,它可以是某种类型,具有某些属性等。某些属性的存在可以推断出类型,或者某些类型的存在可以推断出其他类型。您无法使用简单的 django 数据模型轻松描述此信息。您需要的是一个上下文感知的推理图形存储,例如 AllegroGraph,或者使用 rdflib 实现您的破解解决方案。

      【讨论】:

      • 您在这里混合了多个问题。歌手和忍者可能需要不同的属性,但这绝不意味着你突然有了一个完全开放的动态模式。表示一种人特有的知识的明显而简单的方法是,除了 person 表之外,还有一个包含有关歌手的事实的歌手表、相应的 ninja 表等。所有表都将具有 person_id 的 PK,并酌情使用 FK。
      【解决方案4】:

      多重继承不适用于数据库(您的 Django 模型最终确实需要映射到数据库),并且继承通常是对“角色”建模的不好方法(因为人们的角色确实会改变)。我会将 Singer、Bassist 和 Ninja 作为“角色”,not 作为 Person 的子类,并通过外键连接它们:

      class Singer(models.Model):
          person = models.ForeignKey('Person')
          # ...
      
      class Person(models.Model):
          # ...
      

      【讨论】:

      • @Alex:不是通过多重继承将角色组合在一起,还有其他方法可以将它们合并在一起吗?我对使用 FK 将角色与 Person 类配对感到不安,因为 Person 的信息完全取决于他们是谁。也许我应该多考虑一下,非常感谢亚历克斯!
      • 这是要走的路,除非“歌手”只不过是一个描述符......在这种情况下,只需将 is_singer = models.BooleanField() 添加到 Person 模型中就可以简化模型和更快的查询
      • 这些是角色,而不是子类。传统的基于类的单一继承分类法中的子类是互斥的。例如,Dog、Cat 和 Bunny 都可以从 Mammal 继承,但没有动物可以同时是 Dog Bunny。支持多重继承的语言对此类事情更宽容,但在这种情况下,我同意 Alex 的观点,即使用继承将是一个建模错误,即使它很容易工作。
      • @Radiant,用thisperson.singer_set.all()之类的有什么问题?
      • @Radiant,看起来歌手和忍者可能有一个共同点 model 和一个 identity - 这太少付钱了将继承强加到关系基板上的巨大代价,再加上 multiple 继承的巨大进一步复杂性(!),就更不用说了。只需给两个模型一个名称和一个 personID 属性,忘记 person 模型,并且——如果你需要它来实现高级业务逻辑——一个 应用程序级 Person 类(not 一个模型!),它根据需要处理 1+ 个实际模型实例的数据库获取和存储,以及行为部分(策略 DP 建议)。
      猜你喜欢
      • 2018-07-07
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-29
      相关资源
      最近更新 更多