在 Django 模型类上设置 __new__ 是否安全?

发布于 2025-01-07 08:15:23 字数 1536 浏览 3 评论 0原文

这个问题不同于: 在类上使用 __new__从 Django 模型派生的代码不起作用

这个问题询问如何使 __new__ 工作。

这个问题问:将 __new__ 与 Django 模型一起使用有哪些陷阱?

特别是,我有以下代码,它的存在是为了在类上安装一个类方法,它需要知道它源自哪个类(即它需要告诉它是否在子类上调用)。 这会以意想不到的方式爆炸吗?

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 属性来模拟从一个子类更改为另一个子类的模型子类实例。

This question is different from: Using __new__ on classes derived from Django's models does not work

That question asks how one can make __new__ work.

This question asks: What are the pitfalls of using __new__ with Django models?

In particular, I have the following code, which exists to install a classmethod on the class, which needs to know which class it originates in (i.e. it needs to tell whether it is being called on a subclass or not). Will this blow up in unexpected ways?

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)

For completeness, create_subclass_translator does something like this:

@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

For those who wonder what this is accomplishing, the classmethod create_from_other_instance is a factory which simulates a model subclass instance changing from one subclass to another, by copying over the baseclass properties, and setting the ancestor_link property correctly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

摘星┃星的人 2025-01-14 08:15:23

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

那里不应该有任何微妙的错误 - 只需编写一些实例化此类的单元测试即可。如果它变得“错误”,测试就会失败。

Since you are properly calling the base class __new__, I would not expect surprises there - it should just work - and if done wrong, fail at once at instantiation.

You should not have any subtle errors there - just write some unit tests that instantiate this class. If it ever become "wrong" the tests will fail.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文