看看这个changeset for Django。我需要这个功能,但是这个补丁来自Django的1.7版本,我不能在我的环境中使用它(仅限Python 2.6 )。所以现在,我已经将admin_view方法复制到我的代码中,并用admin.site.admin_view = partial(admin_view, admin.site)注入它。
然而,我希望将“分支”代码的数量保持在最少,并想知道:是否可以对其进行monkeypatch,即在装饰器的inner函数的执行范围内用redirect_to_login替换self.login函数?
我知道这将是一个邪恶的黑客攻击,然而,我想知道一个人可以用Python走多远。
发布于 2014-12-02 01:44:27
django.contrib.admin.sites.inner = yourfunctionhere
编辑:
哇。有点尴尬我让它在这里放了这么久。我依稀记得我基于第二个方法的那篇文章(见下面的评论),但我记不起足够多的细节来再次找到它。因此,我只推荐将AdminSite子类化。
编辑2:经过一些搜索,我发现了这个:
Does an equivalent of override exist for nested functions?
'monkey_patch_fn‘函数做了您想要做的事情,并演示了一种可能的方法。它可能不完整,也可能不完整。
我最初的计划是通过反汇编来修改该函数,但我遇到了属性为只读的问题(我认为这就是我最初的文章所处理的问题……但是我找不到它)。
编辑3:
使用名为byteplay的模块找到了另一种方法。很高兴我没有这么快就放弃。我更喜欢这种方式。它可能只是在引擎盖下的黑客,但我相信一个完整的成熟的发布模块会更加小心,而不是对特定问题的随机答案。
不管怎么说。因为我现在不想看Django代码,所以我将提供一个应该足够的示例。首先,设置。
from byteplay import *
import dis
def test():
def printone():
print 1
printone()
def printtwo():
print 2
dis.dis(test)这里的输出将是
2 0 LOAD_CONST 1 (<code object printone at 0x7f72097371b, file "<stdin>", line 1>)
3 MAKE_FUNCTION 0
6 STORE_FAST 0 (printone)
4 9 LOAD_FAST 0 (printone)
12 CALL_FUNCTION 0
15 POP_TOP
16 LOAD_CONST 0 (None)
19 RETURN_VALUE 因此,我们使用byteplay将其转换为Code对象,对其进行编辑,然后将其转换回常规字节码。
testcode = Code.from_code(test.__code__)
print testcode.code输出为:
[(SetLineno, 2), (LOAD_CONST, <byteplay.Code object at 0x7f72096e6a50>), (MAKE_FUNCTION, 0), (STORE_FAST, 'printone'), (SetLineno, 4), (LOAD_FAST, 'printone'), (CALL_FUNCTION, 0), (POP_TOP, None), (LOAD_CONST, None), (RETURN_VALUE, None)]这是dis的镜像。因此,我们需要更改第二个元组中的Code对象,并将新代码放入原始对象中。
testcode.code[1] = (LOAD_CONST, Code.from_code(printtwo.__code__))
test.__code__ = testcode.to_code()
dis.dis(test)
test()输出有点乱,但我们可以看到:
5 0 LOAD_CONST 1 (<code object printtwo at 0x7fc668476230, file "byteplaytest.py", line 9>)
3 MAKE_FUNCTION 0
6 STORE_FAST 0 (printone)
7 9 LOAD_FAST 0 (printone)
12 CALL_FUNCTION 0
15 POP_TOP
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
2因此,我们加载printtwo函数,将其保存为本地变量名printone下的函数,然后最终的2就是被成功调用的printtwo函数。
这应该全面地说明你需要做什么。您将需要使用dis来确定需要更改字节码中的哪一行,但我认为您应该只需要更改LOAD_CONST。诚然,我没有尝试过使用库或其他任何东西。但如果有什么问题请告诉我。
https://stackoverflow.com/questions/27233460
复制相似问题