在Django中使多表继承设计通用

5 投票
2 回答
1436 浏览
提问于 2025-04-15 15:53

首先,这里有一些我参考过的链接:一个StackOverflow的问题,还有Django文档中的通用关系多表继承

到目前为止,我已经设置了一个多表继承的设计。对象(比如:汽车、狗、电脑)可以继承一个叫做Item的类。我需要从数据库中获取Items,找到它们的子类,然后进行操作。我的设计不允许我逐个获取不同类型的对象,所以我需要用Item这个容器把它们都包裹在一起。一旦我得到了Item,Django文档说我可以通过引用模型名称的属性来获取子类(例如:myitem.car或myitem.computer)。

但我不知道我的Item引用的是哪种类型的对象,那我该怎么获取子类呢?有没有什么内置的方法可以做到这一点?我还有一些其他的想法:(有些比其他的更疯狂)

  1. 我在想可以给Item添加一种GenericForeignKey,来引用子类,但我怀疑父类通过ForeignKey与子类关联是否合规。
  2. 我可以在Item类中添加一个ForeignKey(ContentType),然后根据ContentType的名称找到Item的属性来获取子类。
  3. 最后,虽然这个方法不太优雅,但我可以保持一个对象类型的列表,逐个尝试作为属性,直到没有抛出DoesNotExist错误为止。

如你所见,这些提议的解决方案都不是特别优雅,但我希望我不需要使用其中的任何一个,也许这里有人能提供更好的建议。

提前谢谢你们!

2 个回答

1

最好是把一个物品模型和一个物品类型模型组合在一起。虽然把模型进行子类化听起来不错,并且在一些特殊情况下确实有用,但一般来说,遵循与数据库兼容的方法会更安全、更有效,而不是与数据库对着干。

5

我在我的一个项目中做过类似方法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)

撰写回答