gpt4 book ai didi

python - Django中的多态模型继承

转载 作者:行者123 更新时间:2023-12-03 15:40:25 26 4
gpt4 key购买 nike

这个问题是关于 Django 中的模型继承。

我读过的几乎所有内容(包括 Django 文档本身)都强烈建议执行 '抽象基类' 继承而不是 '多表' 遗产。
我同意推理,因此完全支持该建议。然而,Django 没有
似乎支持:

  • 多态查询,或
  • 模型链接(即我无法从另一个模型创建一个指向抽象基类的 ForeignKey 字段)。

  • 情况

    例如,我有一些实现“抽象基类”继承模式的模型:
    class Tool(models.Model):
    name = models.CharField(max_length=30)
    group = models.ManyToManyField(ToolGroup, blank=True) # Link to 'ToolGroup' MUST be placed on abstract class
    attributes = models.ManyToManyField(ToolAttributeValue, blank=True) # Link to 'ToolAttributeValue' MUST be placed on abstract class

    class Meta:
    abstract = True # Almost everything I read strongly recommends against making this its own table


    class HandheldTool(Tool):
    electrical_safe = models.BooleanField(default=False)


    class PowerTool(Tool):
    compliance_expiry_date = models.DateTimeField()


    class ConsumableTool(Tool):
    combustible = models.BooleanField(default=False)
    best_before = models.DateTimeField(null=True)

    我也有一些与一般工具相关的分组和信息类:
    # Grouping related structures
    #
    # ToolHierarchy > ToolGroup (n times) > Tool
    #
    # "Tool Boxes" > "Day Shift" > "Builders" > HandheldTool[Hammer]
    # > HandheldTool[Screwdriver - SAFE]
    # > PowerTool[Drill]
    #
    # > "Demo Team" > HandheldTool[Sledgehammer 1]
    # > PowerTool[Jackhammer]
    # > ConsumableTool[Dynamite]
    #
    # > "Night Shift" > "Rock Breakers" > HandheldTool[Hammer]
    # > HandheldTool[Sledgehammer 2]
    # > PowerTool[Rocksaw]

    class ToolHierarchy(models.Model):
    name = models.CharField(blank=True, max_length=30)


    class ToolGroup(models.Model):
    name = models.CharField(blank=True, max_length=30)
    parent = models.ForeignKey('self', related_name='children', null=True, blank=True)
    hierarchy = models.ForeignKey(ToolHierarchy, null=True, blank=True, related_name='top_level_tools')
    # tools = models.ManyToManyField(Tool) # CANNOT MAKE LINK, as 'Tool' is abstract


    # 'Extra-info' structures
    #
    # ToolAttribute > ToolAttributeValue > Tool
    #
    # 'Brand' > 'Stanley' > HandheldTool[Hammer]
    # > HandheldTool[Sledgehammer 1]
    # > 'ACME' > HandheldTool[Sledgehammer 2]
    # > ConsumableTool[Dynamite]
    #
    # 'Supplier' > 'Bash Brothers' > HandheldTool[Hammer]
    # > HandheldTool[Sledgehammer 1]
    # > HandheldTool[Sledgehammer 2]
    class ToolAttribute(models.Model):
    name = models.CharField(max_length=30)
    data_type = models.CharField(max_length=30) # e.g. "STRING", "INT", "DATE" "FLOAT" -- Actually done with enum
    unit_of_measure = models.CharField(max_length=30, blank=True)


    class ToolAttributeValue(models.Model):
    attribute = models.ForeignKey(ToolAttribute)
    value = models.CharField(blank=True, max_length=30)
    # tool = models.ForeignKey(Tool) # CANNOT MAKE LINK, as 'Tool' is abstract

    问题

    理想情况下,这种继承模型将通过多态关系实现,但是 Django ORM 没有
    支持它。这对于 SQLAlchemy 和其他 ORM(如 Hibernate)是可能的。

    使用 Django ORM,因为 Tool类是抽象的 I 不能创建如下链接:
  • ToolAttributeValue.tool -> tool_obj
  • ToolGroup.tools -> [tool_obj_1, tool_obj_2] .

  • 相反,我被迫在抽象类上创建反向链接,尽管它建模略有不同!这会导致 ToolAttributeValue 上出现各种丑陋的情况。和 ToolGroup对象,然后不再具有 .tools属性,而是有 RelatedManager每个子类型的字段。 IE。:
    tool_group_obj.handheldtool_set.all()
    tool_group_obj.powertool_set.all()
    ...etc, for every subtype of Tool

    这几乎破坏了抽象类的有用性。

    问题

    因此,考虑到这一点,我的问题是:
  • 这是“多表”继承的好例子吗?
  • 我是否过于努力地强制类型继承?我应该摆脱Tool ?如果是,那么我是否必须创建一个 *ToolGroup每个子类的模型?
  • 当前(Django 1.8)接受的解决方法是什么?当然,我不是第一个在 Django 中构建关系系统的人 ;-) 其他 ORM 已经考虑过这个问题的事实表明它是一种常见的设计选择。
  • 多态解决方案(可能通过 SQLAlchemy)是一种选择吗?这是否正在考虑用于 Django 1.9+?

  • 注意:我已阅读文档并测试了 https://github.com/chrisglass/django_polymorphic ,但它似乎不起作用
    用于“抽象基类”继承(即仅适用于多表)。如果我确实选择了多表继承,那么
    django-polymorphic 对我的问题的查询方面有好处,我想我的模型链接问题会消失。

    注意:这是一个与 this one 类似的问题。 ,但提供了更多细节。

    最佳答案

    好吧,所以我想我会回答我自己的问题......

  • 这是“多表”继承的好例子吗?

    看起来是这样。尽管有一些地方建议不要使用“多表”继承 (listed here for example),但一些反对意见是:
  • @Bruno Desthuilliers 指出这些意见并非来自“官方”文档,并且通过扩展,他暗示“多表”是一个非常好的功能可供使用。
  • 我对@dhke 的链接和评论的阅读是,您必须选择一个选项,并且“多表”选项是数据库真正支持继承的唯一方式。 IE。即使使用 Hibernate 或 SQLAlchemy 等工具的多态技巧,您仍然需要选择是 JOIN 表('multi-table' 选项)进行对象查找还是 UNION 表('abstract base'/'polymorphic' 选项)来创建集合。
  • @dhke 还指出,最好使用“多表”选项并告诉像 django-polymorphic 这样的库。在查找“整体”时不要进行子类解析,而不是让数据库对所有表执行 UNION(使用“抽象基类”选项进行“整体”查找时需要)。
  • 我是否过于努力地强制类型继承?我应该摆脱Tool ?如果是,那么我是否必须创建一个 *ToolGroup每个子类的模型?

    不,似乎不是这样。 Tool 的两种用途我提出的界面有不同的需求:
  • ToolGroup/分层分组用例是保留继承的Tool的好用例类(class)。如果您必须为每种类型的工具创建一组特定于类型的类,这将变得非常难看
  • ToolAttribute也为父类(super class)提供了一个很好的案例,除非您能够使用诸如 HSTORE 字段类型之类的东西(由 Postgres 提供,我不确定其他后端)。 This link给出了一个很好的概要,这可能是我在这里要做的(感谢@nigel222 对问题的研究!)。
  • 当前(Django 1.8)接受的解决方法是什么?当然,我不是第一个在 Django 中构建关系系统的人;-) 其他 ORM 已经考虑过这个问题的事实表明它是一种常见的设计选择。

    现在这是一个无关紧要的问题。基本上他们不担心。
  • 多态解决方案(可能通过 SQLAlchemy)是一种选择吗?这是否正在考虑用于 Django 1.9+?

    不是我能说的。
  • 关于python - Django中的多态模型继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32606262/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com