【问题标题】:Making a multi-table inheritance design generic in Django在 Django 中使多表继承设计通用
【发布时间】:2009-11-11 02:46:01
【问题描述】:

首先,一些指向我用作参考的页面的链接:A SO question,以及 generic relationsmulti-table inheritance 上的 Django 文档。

到目前为止,我已经设置了多表继承设计。对象(例如:汽车、狗、计算机)可以继承 Item 类。我需要能够从数据库中检索项目,获取子类,并用它做一些事情。我的设计不允许一一检索不同种类的对象,所以我需要使用 Item 容器将它们全部包装成一个。一旦我有了项目,Django 文档说我可以通过引用带有模型名称的属性(例如:myitem.car 或 myitem.computer)来获取子类。

我不知道我的项目引用的是哪种类型的对象,那么如何获取孩子?有没有内置的方法来做到这一点?以下是我的其他一些想法:(有些比其他的更疯狂)

  1. 我在想我可以添加一些 GenericForeignKey 到 Item 的 引用了孩子,但我对此表示怀疑 父类甚至是合法的 通过 ForeignKey 与孩子相关联 类。
  2. 我想我可以有一个 项目中的 ForeignKey(ContentType) 类,找到属性 获取孩子的项目基于 内容类型的名称。
  3. 最后,虽然是一个丑陋的方法,但我也许可以保留一个对象类型列表,并尝试将每个对象类型作为一个属性,直到不抛出 DoesNotExist 错误。

如您所见,这些建议的解决方案并不那么优雅,但我希望我不必使用其中一个,并且这里有人可能有更好的建议。

提前致谢

【问题讨论】:

    标签: python django inheritance


    【解决方案1】:

    我在我的一个项目中做了类似于方法 2 的事情:

    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    
    class BaseModel(models.Model):
        type = models.ForeignKey(ContentType,editable=False)
        # other base fields here
    
        def save(self,force_insert=False,force_update=False):
            if self.type_id is None:
                self.type = ContentType.objects.get_for_model(self.__class__)
            super(BaseModel,self).save(force_insert,force_update)
    
        def get_instance(self):
            return self.type.get_object_for_this_type(id=self.id)
    

    【讨论】:

    • 这适用于我的情况,但有没有办法通过多表继承来做到这一点?我知道我可以在上面的代码中使用抽象继承,但恕我直言,真正的多表继承会更干净。但这可能只是我很挑剔:)
    • 凭什么说这不是多表继承?
    • 我对此有一个重要的更正。 'type_ptr' 需要更改为 'type_id'。该行的目的是检查 ContentType 是否已分配并写入数据库。数据库字段是 type_id 而不是 type_ptr。这种差异很重要,因为如果您使用 BaseModel 并调用 save(),则类型将重置为 BaseModel,而实际类型将被清除。否则它会被忽视,但如果发生上述情况,它会变得很糟糕。
    • 我实际上不得不将其更改为“if self.type_id == None:”。另一个更正是一个错字,它永远不会运行。通过我之前提到的更正, if 将永远不会评估并且不会分配类型。如果您使用“if self.type_id == None:”,则只有在尚未分配类型时才会更新类型。
    • 这就是 django-polymorphic 和 django-polymodels 所做的。
    【解决方案2】:

    最好组合一个Item模型和一个ItemType模型的模型。子类化模型听起来不错,并且在一些边缘情况下很有用,但通常,坚持适用于您的数据库而不是反对它的策略是最安全和最有效的。

    【讨论】:

    • 这对数据库有什么影响?
    • 数据库级别不支持继承等面向对象的概念。 ORM 可以提供一些巧妙的方法来固定功能,但它们最终会导致上述问题。 Django 通过创建带有 ForeignKey 的扩展表来实现这一点,但这缺乏任何简单的自省方法。你最终会得到一长串 if/else 或 try/except 块。
    • 如上所示,不需要长系列的 if/else 或 try/except 块。我真的无法想象在数据库级别尝试这样做会更好。
    猜你喜欢
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    相关资源
    最近更新 更多