【发布时间】:2012-03-11 23:37:23
【问题描述】:
这个问题不同于:Using __new__ on classes derived from Django's models does not work
那个问题是问如何让__new__工作。
这个问题问:在 Django 模型中使用__new__ 有什么陷阱?
特别是,我有以下代码,它存在用于在类上安装一个类方法,它需要知道它源自哪个类(即它需要判断它是否在子类上被调用)。 这会以意想不到的方式爆发吗?
class Director(models.Model, Specializable, DateFormatter, AdminURL, Supercedable): # my own mixin classes
# all other properties etc snipped
@staticmethod # necessary with django models
def __new__(cls, *args, **kwargs):
Specializable.create_subclass_translator(cls, install = 'create_from_officer')
return models.Model.__new__(cls, *args, **kwargs)
为了完整起见,create_subclass_translator 做了这样的事情:
@classmethod
def create_subclass_translator(clazz, Baseclass, install=None):
def create_from_other_instance(selfclass, old_instance, properties):
if selfclass is Baseclass: raise TypeError("This method cannot be used on the base class")
# snipped for concision
return selfclass(**properties)
new_method = classmethod(create_from_other_instance)
if install and not hasattr(Baseclass, install):
setattr(Baseclass, install, new_method)
return new_method
对于那些想知道这是做什么的人,create_from_other_instance 类方法是一个工厂,它通过复制基类属性并正确设置 ancestor_link 属性来模拟模型子类实例从一个子类更改为另一个子类。
【问题讨论】:
-
这种复杂性有什么好的理由吗?
-
@Secator:首先,我不认为这特别复杂。无论如何,这样做的原因是我需要在几个类层次结构中具有相同的功能,并且如上所述,这些方法需要了解它们自己的类。要以另一种方式实现这一点,则需要复制和粘贴;或者每个返回该类本身的基类的魔术辅助方法;或在类定义之外执行安装。所有这些都会引发他们自己的微妙错误。
-
你看过BaseModel类吗?我相当肯定它也定义了一个 new 方法。我认为,一旦你在自己的方法中做了你需要做的事情,你就需要调用 super,否则该类将不会按照 Django 期望的方式实例化。值得注意的是,您不会有 Meta 类或 Media 类(在适当的情况下)。这些只是我脑海中的一些想法。
-
@JamesR:我会看看 BaseModel。请注意,django.models.Model 继承自 BaseModel,我在上面调用 new。还是有理由使用
super而不是使用基类的名称? -
否 - 如果基类在项目生命周期内没有变化,您可以按名称调用基类。 “超级”有时可能相当不直观。
标签: python django django-models metaprogramming django-orm