我是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中的相同角色名称)。
约束:
由于子类(RolaA,RoleB等)不添加新字段但只覆盖方法,所有数据都必须存储在Player的表中,所以我不想使用Django多表继承但是更类似于Proxies。
我不想执行额外的JOIN来确定特定的子类类型,因为所需的所有信息都存储在Player的表中。
我认为这是一个标准的多态模式但是我没有看到如何在Django中为所有玩家使用相同的表来实现它(我已经实现了这个多态但没有链接到Django模型)。我见过Django有一种名为“Proxy”的继承,但它不允许像Player.objects.filter(...)那样进行查询,并且用自定义方法覆盖方法来获取实例(或者至少这是我理解的)。
提前致谢。
答案 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
(或RoleA
,RoleB
等)的实例是否具有可调用属性allow_action()
以及是否所以,它会使用它,否则它将使用默认值。