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

Cha*_*uin 53 python django

我知道如何在常规Python解释器会话中重新加载常规Python模块.这个问题记录了如何做得很好:

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

出于某种原因,我在Django的"manage.py shell"解释器会话中遇到了麻烦.要重新创建我的问题,请启动此处的基本Django教程:

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

创建"民意调查"应用程序和"民意调查"类后,通过"manage.py shell"启动解释器并将"民意调查"应用程序导入其中.

import polls.models as pm
Run Code Online (Sandbox Code Playgroud)

创建一个新的"民意调查"对象:

p = pm.Poll()
Run Code Online (Sandbox Code Playgroud)

到目前为止一切顺利.现在回到您的源代码并添加任意方法或属性.例如,我添加了:

def x(self):
    return 2+2
Run Code Online (Sandbox Code Playgroud)

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

reload(pm)
Run Code Online (Sandbox Code Playgroud)

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

p1 = pm.Poll()
p1.x()
Run Code Online (Sandbox Code Playgroud)

你会收到这条消息:

'Poll' object has no attribute 'x'
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?我还尝试重新运行import命令,使用不同的语法导入模块,删除对任何"Poll"对象或"Poll"类的所有引用.我也尝试过使用IPython解释器和普通的Python(v2.6)解释器.似乎没什么用.

在常规解释器会话中使用与任意Python模块相同的技术可以很好地工作.我似乎无法让它在Django的"shell"会话中工作.

顺便说一句,如果它有任何区别,我在Ubuntu 9.04机器上这样做.

Cha*_*uin 38

好吧,我想我必须回答这个问题.问题是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
Run Code Online (Sandbox Code Playgroud)

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

%run ~/mysite/reloadmodels.py
Run Code Online (Sandbox Code Playgroud)

  • 我将在脚本的开头添加以下两行:import os; os.system('del*.pyc/s> NUL')或linux的等价物 (2认同)
  • 这对我来说似乎不适用于使用Django 1.6.似乎至少`cache.handled`应该设置为`set()`(否则你甚至不能运行reloadmodels.py两次). (2认同)

mpa*_*paf 6

您还可以使用以下命令使用django-extensions项目:

manage.py shell_plus --notebook
Run Code Online (Sandbox Code Playgroud)

这将在您的Web浏览器上打开一个IPython笔记本,而不是IPython shell解释器.在那里编写代码并运行它.

更改模块时,只需单击网页菜单项'Kernel-> Restart'

现在重新运行代码会使用您修改过的模块.


PAD*_*MKO 6

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

1.安装django_extension

2.添加下一个设置:

SHELL_PLUS = 'ipython'

IPYTHON_ARGUMENTS = [
    '--ext', 'autoreload',
]
Run Code Online (Sandbox Code Playgroud)

3,运行shell

./manage.py shell_plus
Run Code Online (Sandbox Code Playgroud)

查看结果:

模型实例

class Notification(models.Model):

    ........

    @classmethod
    def get_something(self):

        return 'I am programmer'
Run Code Online (Sandbox Code Playgroud)

带壳

In [1]: Notification.get_something()
Out[1]: 'I am programmer'
Run Code Online (Sandbox Code Playgroud)

对模型进行了更改

@classmethod
    def get_something(self):

        return 'I am Python programmer'
Run Code Online (Sandbox Code Playgroud)

带壳

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

在外壳中。这是魔术

# configure extension of ipython
In [3]: %autoreload 2
Run Code Online (Sandbox Code Playgroud)

带壳

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

再次进行更改

    @classmethod
    def get_something(self):

        return 'I am full-stack Python programmer'
Run Code Online (Sandbox Code Playgroud)

带壳

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

缺点:1.需要手动运行代码

%自动重载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()的地方更改代码,则可能会产生错误。


sur*_*aar 5

假设您的项目以这种方式设置

  • 项目名称:书店
  • 应用名称:货架
  • 型号名称:书籍

第一次加载

from bookstore.shelf.models import Books
Run Code Online (Sandbox Code Playgroud)

随后的重新加载

import bookstore;reload(bookstore.shelf.models);from bookstore.shelf.models import Books
Run Code Online (Sandbox Code Playgroud)


Tom*_*ski 5

就我而言,上述解决方案都没有自行解决,这个线程本身也没有多大帮助,但在结合这些方法后,我设法在shell_plus中重新加载我的模型:

  1. 对模型进行更改(MyModel)
  2. 去掉 models.pyc
  3. 清理Django模型缓存(像这里):

     from django.db.models.loading import AppCache
     cache = AppCache()
     from django.utils.datastructures import SortedDict
     cache.app_store = SortedDict()
     cache.app_models = SortedDict()
     cache.app_errors = {}
     cache.handled = {}
     cache.loaded = False
    
    Run Code Online (Sandbox Code Playgroud)
  4. 这里重新加载模型

    reload(project.app.models)
    from project.app.models import MyModel
    
    Run Code Online (Sandbox Code Playgroud)