Django模型多态性没有多表继承和额外的JOIN

时间:2014-02-21 12:45:48

标签: python django inheritance django-models

我是Django的新手,我正在尝试在Django模型中实现多态,但我看不到该怎么做。在继续之前,我不得不说我已经尝试过django-model-utils和django-polymorphism,但它们并没有完全符合我的要求。

我有一个名为Player的模型,每个玩家都有一个角色,每个角色都有不同的行为(即他们的方法返回不同的值):

class Player(models.Model):
    username=models.TextField()
    role=models.ForeignKey(Role)    #Role is another model with a field called ’name'

    def allow_action(self)
         #some stuff

class RoleA():
    def allow_action(self):
         #some specific stuff

class RoleB():
    pass

我希望每次检索Player的任何实例时(例如通过Player.objects.filter(...)),每个实例都会在特定类(RoleA,RoleB)中定义的自定义方法覆盖allow_action()方法。等等...)或者使用Player中提供的默认方法,如果相关的子类没有使用相同名称调用的方法(RoleA,RoleB等...是存储在Player.role.name中的相同角色名称)。

约束:

  1. 由于子类(RolaA,RoleB等)不添加新字段但只覆盖方法,所有数据都必须存储在Player的表中,所以我不想使用Django多表继承但是更类似于Proxies。

  2. 我不想执行额外的JOIN来确定特定的子类类型,因为所需的所有信息都存储在Player的表中。

  3. 我认为这是一个标准的多态模式但是我没有看到如何在Django中为所有玩家使用相同的表来实现它(我已经实现了这个多态但没有链接到Django模型)。我见过Django有一种名为“Proxy”的继承,但它不允许像Player.objects.filter(...)那样进行查询,并且用自定义方法覆盖方法来获取实例(或者至少这是我理解的)。

    提前致谢。

1 个答案:

答案 0 :(得分:0)

免责声明:我没有使用django-polymorphic,此代码基于扫描文档花了5分钟,而且完全没有经过测试,但我很想知道它是否有效:

from polymorphic import PolymorphicModel


class Role(PolymorphicModel):
    name = models.CharField()


class RoleA(Role):
    def allow_action(self):
        # Some specific stuff...


class RoleB(Role):
    pass


class Player(models.Model):
    username=models.TextField()
    role=models.ForeignKey(Role)    #Role is another model with a field called ’name'

    def allow_action(self)
        if callable(getattr(self.role, "allow_action", None):
            self.role.allow_action()
        else:
            # default action...

现在我相信您应该能够创建Role,RoleA或RoleB的实例,并让Player在外键中指向它。在Player实例上调用allow_action()将检查Role(或RoleARoleB等)的实例是否具有可调用属性allow_action()以及是否所以,它会使用它,否则它将使用默认值。