从非抽象模型继承而不使用多表继承

2 投票
2 回答
1421 浏览
提问于 2025-04-18 14:50

有没有办法从一个已经存在的模型继承,以便在不使用多表继承的情况下,复制它的所有字段(遵循DRY原则)?前提是这个模型不是abstract的。

我想说的是,我有一个模型叫Post,我想要另一个模型GhostPost,它的字段和Post完全一样,但我不想让它和Post有多表继承或任何关系。问题是,Post不是一个抽象模型,所以Django会启动多表继承。有没有办法解决这个问题?

更新: 我想要的不是一个Python层面的模型副本,而是一个实际的、独立的数据库表,能够反映这些字段。

解决方案:我听从了@Brandon的建议,使用了一个抽象模型。

2 个回答

0

你可以添加一个额外的布尔字段 is_ghost,然后在原始模型和代理模型上重写默认的管理器:

class PostManager(models.Manager):
    def get_querset(self):
        return super(PostManager, self).get_queryset().filter(is_ghost=False)

class Post(models.Model):
    ...
    is_ghost = models.BooleanField(blank=True, default=False)
    objects = PostManager()

class GhostPostManager(models.Manager):
    def get_queryset(self):
        return super(GhostPostManager, self).get_queryset().filter(is_ghost=True)

class GhostPost(Post):
    objects = GhostPostManager()

    Meta:
        proxy = True

这样做会把所有内容保存在一个表里,但管理器和查询集的行为就像它们是两个独立的模型或表一样。

另一种解决方案是为这两个模型使用一个抽象基类。如果你不改变原始 Post 模型的类名,而是从比如说 AbstractPost 继承,我认为这样做不会有什么问题。

3

在这种情况下,你需要使用代理模型。它可以让你扩展一个不是抽象的模型,但又不需要多表继承。你可以查看这个链接了解更多信息:https://docs.djangoproject.com/en/1.6/topics/db/models/#proxy-models

代理模型会保持在一个表里,所以如果你需要为每个模型创建一个表,我建议你为PostGhostPost模型创建一个共同的抽象类来继承。

撰写回答