【问题标题】:Is it safe to set __new__ on Django model classes?在 Django 模型类上设置 __new__ 是否安全?
【发布时间】: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


【解决方案1】:

由于您正确地调用了基类 __new__,因此我不希望那里出现意外 - 它应该可以正常工作 - 如果做错了,在实例化时立即失败。

你不应该有任何细微的错误 - 只需编写一些实例化此类的单元测试。如果它变得“错误”,测试将失败。

【讨论】:

  • 谢谢。当然,如果我知道可能的故障模式,我会专门测试那些;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
  • 2012-10-08
  • 1970-01-01
  • 2014-10-19
相关资源
最近更新 更多