我有一个模特
BaseModel
及其几个子类
ChildModelA(BaseModel), ChildModelB(BaseModel), ...
使用多表继承。将来我计划有几十个子类模型。
所有子类都有一些方法
的实现do_something()
如何从BaseModel实例调用do_somthing?
几乎完全相同的问题(没有解决方案)张贴在这里:
http://peterbraden.co.uk/article/django-inheritance
一个更简单的问题:如何在不检查所有可能的子类的情况下将BaseModel instnace解析为其子类实例之一?
答案 0 :(得分:2)
如果你想避免检查所有可能的子类,我能想到的唯一方法是将与子类关联的类名存储在基类定义的字段中。您的基类可能有这样的方法:
def resolve(self):
module, cls_name = self.class_name.rsplit(".",1)
module = import_module(module)
cls = getattr(module, cls_name)
return cls.objects.get(pk=self.pk)
这个答案并没有让我高兴,我也很乐意看到更好的解决方案,因为我很快就会遇到类似的问题。
答案 1 :(得分:1)
您是否会使用基类型的实例,或者您是否一直在处理子项的实例?如果是后一种情况,则调用该方法,即使您具有对基类型的引用,因为对象本身是IS-A子类型。
由于Python支持duck typing,这意味着您的方法调用将是适当的绑定,因为子实例将真正拥有此方法。
一种pythonic编程风格 确定对象的类型 检查其方法或属性 签名而不是明确的 与某种类型对象的关系(“如果 它看起来像一只鸭子,像一个嘎嘎叫 鸭子,它一定是鸭子。“) 强调接口而不是 特定类型,精心设计的代码 通过允许来提高其灵活性 多态替换。鸭打字 避免使用type()或 isinstance()。 (但请注意 鸭子打字可以补充 抽象基类。)相反,它 通常使用hasattr()测试或 EAFP编程。
请注意,EAFP代表Easier to Ask Forgiveness than Permission:
比获得许可更容易请求宽恕。这种常见的Python编码风格假设存在有效的键或属性,并且如果假设被证明是错误则捕获异常。这种干净和快速的风格的特点是存在许多try和except语句。该技术与许多其他语言(如C。
)共有的LBYL风格形成对比
答案 2 :(得分:0)
我同意安德鲁。在几个站点上,我们有一个类支持一大堆方法(但不是字段(这是ORM之前的重构)),这些方法对于大多数但并非全部的内容类都是通用的。他们利用hasattr来回避这种方法没有意义的情况。
这意味着我们的大多数课程都被定义为:
class Foo(models.Model, OurKitchenSinkClass):
基本上它是一种MixIn类型的东西。效果很好,易于维护。