如何给 Django 打猴子补丁?
我发现了这篇关于猴子修补 Django 的帖子:
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)
我明白这并不理想,最好通过单独的模型 Profile
向 User
添加字段和函数。
话虽如此,我只想了解这是如何工作的:
我将猴子修补代码放在哪里?
代码什么时候运行——只运行一次?每次Python解释器启动一次?每个请求一次?
大概我仍然需要更改数据库架构。因此,如果我删除表
User
并运行./manage.pysyncdb
,syncdb
会“知道”新字段已添加到用户
?如果不是,我该如何更改架构?
I came upon this post on monkey patching Django:
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)
I understand that this isn't ideal and it's better to add fields and functions to User
through a separate model Profile
.
With that said, I just want to understand how this would work:
Where would I put the monkey patching code?
When is the code run -- just once? once per Python interpreter startup? once per request?
Presumably I'd still need to change the DB schema. So if I dropped the table
User
and ran./manage.py syncdb
, wouldsyncdb
"know" that a new field has been added toUser
? If not how do I change the schema?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
将文件
monkey_patching.py
放入任何应用
中,并将其导入到应用的__init__.py
文件中。即:app/monkey_patching.py
app/__init__.py
put the file
monkey_patching.py
in any of yourapps
and import it in app's__init__.py
file. ie:app/monkey_patching.py
app/__init__.py
您可以将其放在任何地方,但在设置文件(甚至 urlconf)中经常会看到此类内容的链接。任何可以放置信号的地方也可能是合适的。这段代码确实应该稍微智能一些 - 通常文件会被多次导入,并且您对此无能为力,因此如果您尝试多次运行这样的代码,您可能会遇到问题。
每个 python 进程至少需要执行一次代码。
是的,您需要手动更改数据库。 Syncdb可能不会捕获更改(我没有仔细查看代码),但可能在某些地方可以放置可以工作的代码。
您似乎已经知道这是一件非常非常可怕的事情,并且永远不应该对真正的代码执行此操作,因此我不会详细说明这一点。做这种事情是一种极好的方法,可以在代码中生成很难找到的错误,此外还可能会出现在未来版本的 Django 中无法工作的代码。
此外,它不适用于您应该使用的 South。
You could put it anywhere, but it's common to see this kind of stuff linked in the settings file (or even the urlconf). Anywhere you could put a signal might also be appropriate. This code should really be slightly more intelligent - often files get imported more than once and there's not a lot you can do about it, so you can run into problems if you try to run code like this multiple times.
The code needs to be executed at least once for each python process.
Yes you would need to change the DB by hand. Syncdb probably wouldn't catch the change (I haven't looked closely at the code), but there might be some places you could put the code that would work.
You seem to already know that this is a terrible, horrible thing to do and should never be done for real code, so I won't belabor that point. Doing this kind of thing is a fantastic way to generate really difficult to find bugs in your code, in addition to code that may not work in future versions of Django.
Also, it won't work well with South, which you should be using.
使用 @suhailvs 和 @Paul McMillan 的建议,我在应用程序的根目录中添加了一个
patch.py
文件,并在应用程序的apps.py
中调用了我的 patched < code>ready 信号:AppRegistryNotReady:应用尚未加载。
是由于导入而不是函数调用而发生的,因此它必须位于函数内部。Using both @suhailvs and @Paul McMillan's suggestions I added a
patch.py
file to the root of my app, and inside the app'sapps.py
called my patched in theready
signal:The
AppRegistryNotReady: Apps aren't loaded yet.
happens because of the import, not the function call, so it must be inside the function.