如何从其他模块向 Django 类添加新方法? [复制]

Posted

技术标签:

【中文标题】如何从其他模块向 Django 类添加新方法? [复制]【英文标题】:How to add new method to Django class from other modules? [duplicate] 【发布时间】:2015-04-19 22:06:46 【问题描述】:

我有一个 Django 模型说:

class MyOperation(models.Model):
    name = models.CharField(max_length=100)

    def my_method(self):
        pass

我希望能够从不同的 Django 应用程序向此类添加新方法。

我尝试从另一个名为 custom.py 的应用模块中执行此操作:

from operations.models import MyOperation

def op_custom(test):
    print "testing custom methods"

MyOperation.op_custom = op_custom

但这似乎不起作用,在运行时该方法不存在。

这是从不同的 django 应用程序修改类定义的方法吗?有没有更好的方法?

谢谢

【问题讨论】:

1.不要这样做。 2.永远不要这样做。 3. 这会破坏自省,并且会干扰人类对 python 代码的解析,因此不应该这样做。 4.不要。 5. 如果你绝对必须这样做,你可以,正如@knbk 的链接所示。 这不是同一个问题,我问的是如何在 Django 模型中添加方法,我的意思是类,而不是对象。 @JoseLuisdelaRosa 这正是链接的答案,除非我误解了您的实际要求。一个问题 - 你实际上是在运行custom.py 中的代码吗? @astex 什么样的内省不会采用新方法? inspect 模块似乎工作正常。 Tbh 我认为 Django 模型有时是不可避免的。您不能简单地继承第三方模型而没有副作用。 inspect 接收它们,但它们不是来自mro() 中的任何地方。一些 python 库(例如 flask-classy 或我自己的 [private] 项目 foodtoeat.com)使用一个复杂的系统,涉及迭代 mro() 并获取方法的 argspecs 以正确路由到类中的方法。在这些情况下,猴子补丁方法将完全被忽略。 【参考方案1】:

正确的方法是通过 mixin:

class MyMixIn(object):
    def op_custom(self):
        print("foo")

class MyOperation(models.Model, MyMixIn):
    def op_normal(self):
        print("bar")

与另一种方法中的猴子修补相比,这有几个优点:

mixin 在课堂上的method resolution order,因此内省完美运行。 保证在类的每个实例上都定义它,而不管它在哪里实例化,因为类本身继承自 mixin。否则,您可能会在应用猴子补丁之前得到没有此方法的实例。 它为将来添加此类方法提供了一个明显的地方。

【讨论】:

不应该反转模型的继承,例如MyMixIn 应该排在他的models.Model 之前? class MyOperation(MyMixIn, models.Model) @TimSchneider 这取决于预期用途。如果 mixin 应该覆盖 Model 类中的方法,那么可以。但是,某些情况下需要相反的情况。例如,可以使用 mixin 通过编写自定义 save(), ... 方法来“欺骗”模型类,同时通过上述方式提供可用于真实模型的附加功能。 这既不能回答问题,也不能达到同样的目的。将 Mixin 添加到原始实例的 __bases__ 可能会改善答案。

以上是关于如何从其他模块向 Django 类添加新方法? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何向预训练的对象检测模型添加其他类并训练它以检测所有类(预训练 + 新)?

在 Django 中向序列化响应添加附加数据

在 Rails 中,如何向 String 类添加新方法?

如何向 django-oscar 添加新视图

如何向编译安装好的软件添加新模块

如何使用 django 向输入字段添加其他属性? [复制]