【问题标题】:How to monkey patch Django?如何猴子补丁Django?
【发布时间】:2011-10-06 22:39:44
【问题描述】:

我在猴子修补 Django 时遇到了这个 post

from django.contrib.auth.models import User

User.add_to_class('openid', models.CharField(max_length=250,blank=True))

def get_user_name(self):
    if self.first_name or self.last_name:
        return self.first_name + " " + self.last_name
    return self.username

User.add_to_class("get_user_name",get_user_name)

我知道这并不理想,最好通过单独的模型ProfileUser 添加字段和函数。

话虽如此,我只是想了解它是如何工作的:

  1. 猴子补丁代码应该放在哪里?

  2. 代码何时运行——只运行一次?每次 Python 解释器启动一次?每个请求一次?

  3. 大概我仍然需要更改数据库架构。因此,如果我删除表User 并运行./manage.py syncdbsyncdb 会“知道”一个新字段已添加到User 吗?如果不是,我该如何更改架构?

【问题讨论】:

    标签: python django django-models monkeypatching


    【解决方案1】:

    你可以把它放在任何地方,但是在设置文件(甚至是 urlconf)中看到这种东西是很常见的。您可以放置​​信号的任何地方也可能是合适的。这段代码确实应该更智能一些 - 通常文件会被多次导入,而您对此无能为力,因此如果您尝试多次运行这样的代码,可能会遇到问题。

    代码需要为每个python进程至少执行一次。

    是的,您需要手动更改数据库。 Syncdb 可能无法捕捉到变化(我没有仔细查看代码),但可能有些地方可以放置可以工作的代码。

    您似乎已经知道这是一件非常可怕的事情,而且对于真正的代码永远不应该这样做,所以我不会再强调这一点。除了在未来版本的 Django 中可能无法工作的代码之外,这样做是一种极好的方法,可以在代码中生成非常难以发现的错误。

    此外,它不适用于 South,您应该使用它。

    【讨论】:

    • 谢谢。那么设置和 urlconf 文件在每个 Python 进程初始化时运行一次(而且只有一次?)?我总是有点不确定这些文件的运行时间和频率。
    • 不,不一定。他们只是通常不会运行很多次。您根本不能依赖任何文件只运行一次。这就是信号处理程序具有用于唯一性的参数的原因。
    • 我明白了。我不熟悉信号处理程序和您提到的唯一性参数。你能解释一下吗?或者有什么地方可以让我了解更多吗?
    • 查看有关信号调度程序的文档。我指的参数是dispatch_uiddocs.djangoproject.com/en/1.3/topics/signals/…
    【解决方案2】:

    将文件monkey_patching.py 放入您的任何apps 并将其导入应用程序的__init__.py 文件中。即:

    app/monkey_patching.py

    #app/monkey_patching.py
    from django.contrib.auth.models import User
    
    User.add_to_class('openid', models.CharField(max_length=250,blank=True))
    
    def get_user_name(self):
        if self.first_name or self.last_name:
            return self.first_name + " " + self.last_name
        return self.username
    
    User.add_to_class("get_user_name",get_user_name)
    

    app/__init__.py

    #app/__init__.py
    import monkey_patching
    

    【讨论】:

    • 不适用于 django 1.11。我得到 django.core.exceptions.AppRegistryNotReady:应用程序尚未加载。
    • @sureshvv,您可以将其添加到 models.py,并将该应用程序的导入放在 settings.INSTALLED_APPS 中已修补的应用程序上方。然而,迁移仍然存在潜在的混乱......
    猜你喜欢
    • 2010-11-26
    • 1970-01-01
    • 2020-05-24
    • 2016-09-01
    • 2012-09-16
    • 2012-12-18
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多