如何从其他模块向 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 类添加新方法? [复制]的主要内容,如果未能解决你的问题,请参考以下文章