如何通过“manage.py shell”使用交互式解释器重新加载Django模型模块?

7 浏览
0 Comments

如何通过“manage.py shell”使用交互式解释器重新加载Django模型模块?

我知道如何在普通的Python解释器会话中重新加载一个普通的Python模块。这个问题很好地记录了如何做到这一点:

如何卸载(重新加载)Python模块?

出于某种原因,我在Django的“manage.py shell”解释器会话中做到这一点时遇到了困难。为了重新创建我的问题,请在这里找到基本的Django教程:

编写您的第一个Django应用程序,第1部分

在创建“投票(polls)”应用程序和“Poll”类之后,通过“manage.py shell”启动解释器并将“投票”应用程序导入其中。

import polls.models as pm

创建一个新的“投票”对象:

p = pm.Poll()

到目前为止,一切都很好。现在回到你的源代码并添加任意的方法或属性。例如,我添加了:

def x(self):
    return 2+2

现在回到解释器并“重新加载”模块:

reload(pm)

现在尝试使用您的新方法或属性:

p1 = pm.Poll()
p1.x()

你会得到这个消息:

'Poll' object has no attribute 'x'

怎么回事?我也尝试重新运行导入命令,使用不同的语法导入模块,删除所有对任何“投票”对象或“投票”类的引用。我还尝试了使用IPython解释器和普通Python(v2.6)解释器。似乎什么都没有用。

在普通解释器会话中使用同样的技术与任意Python模块完美地运作。我似乎无法在Django的“shell”会话中使其正常工作。

顺便说一下,如果有任何不同,我是在Ubuntu 9.04机器上完成这个任务的。

admin 更改状态以发布 2023年5月20日
0
0 Comments

我在2016年时的解决方案(未来可能会更改)

1. 安装django_extension

2. 添加以下设置:

SHELL_PLUS = 'ipython'
IPYTHON_ARGUMENTS = [
    '--ext', 'autoreload',
]

3. 运行shell

./manage.py shell_plus

查看结果:

模型示例

class Notification(models.Model):
    ........
    @classmethod
    def get_something(self):
        return 'I am programmer'

在shell中

In [1]: Notification.get_something()
Out[1]: 'I am programmer'

对模型进行更改

@classmethod
    def get_something(self):
        return 'I am Python programmer'

在shell中

# shell does not display changes
In [2]: Notification.get_something()
Out[2]: 'I am programmer'

在shell中。这是一种魔法

# configure extension of ipython
In [3]: %autoreload 2

在shell中

# try again - all worked
In [4]: Notification.get_something()
Out[4]: 'I am Python programmer'

再次进行更改

    @classmethod
    def get_something(self):
        return 'I am full-stack Python programmer'

在shell中

# all worked again
In [5]: Notification.get_something()
Out[5]: 'I am full-stack Python programmer'

缺点:

%autoreload 2

因为django_extension 1.7没有支持运行任意代码。也许在将来的版本中会有这个功能。

注意事项:

  1. Django 1.10
  2. Python 3.4
  3. django_extension 1.7.4
  4. 基于https://django-extensions.readthedocs.io/en/latest/shell_plus.htmlhttp://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html
  5. 注意。如果尝试更改使用了super()的代码,则可能产生错误。
0
0 Comments

好的,我认为我必须回答这个问题。问题在于 Django 将其模型缓存到一个叫 AppCache 的单例(类似结构)中。基本上,要重新加载 Django 模型,您需要先重新加载和重新导入存储在 AppCache 中的所有模型模块。然后您需要清除 AppCache。以下是代码:

import os
from django.db.models.loading import AppCache
cache = AppCache()
curdir = os.getcwd()
for app in cache.get_apps():
    f = app.__file__
    if f.startswith(curdir) and f.endswith('.pyc'):
        os.remove(f)
    __import__(app.__name__)
    reload(app)
from django.utils.datastructures import SortedDict
cache.app_store = SortedDict()
cache.app_models = SortedDict()
cache.app_errors = {}
cache.handled = {}
cache.loaded = False

我将所有这些代码放在名为 reloadmodels.py 的单独文件中,放在 Django 站点的根目录中。使用 IPython,我可以通过运行以下命令来重新加载所有内容:

%run ~/mysite/reloadmodels.py

0