101

我正在使用 Django 并一直使用 Django shell。烦人的部分是,当 Django 服务器重新加载代码更改时,shell 不会,所以每次我对正在测试的方法进行更改时,我都需要退出 shell 并重新启动它,重新导入我的所有模块需要,重新初始化我需要的所有变量等。虽然 iPython 历史在这方面节省了很多打字,但这仍然很痛苦。有没有办法让 django shell 自动重新加载,就像 django 开发服务器一样?

我知道 reload(),但是我导入了很多模型并且通常使用from app.models import *语法,所以 reload() 并没有太大帮助。

4

11 回答 11

95

我建议使用 IPython autoreload extension

./manage.py shell

In [1]: %load_ext autoreload
In [2]: %autoreload 2

从现在开始,所有导入的模块都将在评估之前刷新。

In [3]: from x import print_something
In [4]: print_something()
Out[4]: 'Something'

 # Do changes in print_something method in x.py file.

In [5]: print_something()
Out[5]: 'Something else'

%load_ext autoreload如果在命令之前导入了某些内容,也可以使用。

./manage.py shell
In [1]: from x import print_something
In [2]: print_something()
Out[2]: 'Something'

 # Do changes in print_something method in x.py file.

In [3]: %load_ext autoreload
In [4]: %autoreload 2
In [5]: print_something()
Out[5]: 'Something else'

还可以使用%aimport命令和 3 种自动重载策略来防止某些导入刷新:

%自动重载

  • 现在自动重新加载所有模块(除了那些被 %aimport 排除的模块)。

%自动重载 0

  • 禁用自动重新加载。

%自动重载 1

  • 每次执行键入的 Python 代码之前,重新加载所有使用 %aimport 导入的模块。

%自动重载 2

  • 每次执行键入的 Python 代码之前,重新加载所有模块(%aimport 排除的模块除外)。

%进口

  • 列出要自动导入或不导入的模块。

%aimport foo

  • 导入模块 'foo' 并将其标记为自动重新加载 %autoreload 1

%aimport -foo

  • 将模块“foo”标记为不自动重新加载。

这通常适合我的使用,但有一些注意事项:

  • 替换代码对象并不总是成功:将类中的@property 更改为普通方法或将方法更改为成员变量可能会导致问题(但仅限于旧对象)。
  • 在重新加载之前从模块中删除的功能(例如通过猴子补丁)不会升级。
  • C 扩展模块无法重新加载,因此无法自动重新加载。
于 2016-12-14T15:24:38.147 回答
48

我的解决方案是编写代码并保存到文件中,然后使用:

python manage.py shell < test.py

所以我可以进行更改,保存并再次运行该命令,直到我修复我想要修复的任何内容。

于 2014-11-06T03:20:20.327 回答
42

我推荐使用上面 dongweiming 所说的 django-extensions 项目。但不仅仅是“shell_plus”管理命令,请使用:

manage.py shell_plus --notebook

这将在您的网络浏览器上打开一个 IPython 笔记本。将您的代码写在一个单元格中,您的导入等并运行它。

更改模块时,只需单击笔记本菜单项“内核->重新启动”

好了,您的代码现在正在使用您修改后的模块。

于 2013-12-11T07:55:27.697 回答
35

查看django-extensions项目提供的 manage.py shell_plus 命令。它将在 shell 启动时加载所有模型文件。并自动重新加载您的任何修改但不需要退出,您可以直接调用那里

于 2013-05-25T01:17:48.780 回答
25

似乎对这个话题的普遍共识是,python reload() 很糟糕,而且没有好的方法可以做到这一点。

于 2010-09-28T20:32:49.577 回答
8

shell_plus与 ipython 配置一起使用。这将autoreload在 shell_plus 自动导入任何内容之前启用。

pip install django-extensions
pip install ipython
ipython profile create

编辑您的 ipython 配置文件 ( ~/.ipython/profile_default/ipython_config.py):

c.InteractiveShellApp.exec_lines = ['%autoreload 2']
c.InteractiveShellApp.extensions = ['autoreload']

打开一个外壳 - 请注意,您不需要包括--ipython

python manage.py shell_plus

现在在SHELL_PLUS_PRE_IMPORTSor SHELL_PLUS_POST_IMPORTS( docs ) 中定义的任何东西都会自动重新加载!

请注意,如果您的 shell 在pdb.set_trace()您保存文件时处于调试器(例如)中,则它可能会干扰重新加载。

于 2019-04-26T14:33:35.037 回答
7

我对这个不便的解决方案如下。我正在使用 IPython。

$ ./manage.py shell
> import myapp.models as mdls   # 'mdls' or whatever you want, but short...
> mdls.SomeModel.objects.get(pk=100)
> # At this point save some changes in the model
> reload(mdls)
> mdls.SomeModel.objects.get(pk=100)

对于Python 3.x,必须使用以下命令导入“重新加载”:

from importlib import reload

希望能帮助到你。当然,这是出于调试目的。

干杯。

于 2016-10-28T19:49:52.223 回答
5

没有一些技巧,Reload() 在 Django shell 中不起作用。您可以专门检查此线程 na 和我的答案:

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

于 2010-09-22T20:50:13.997 回答
2

为此,我结合使用 2 个答案,提出了一种简单的单行方法。

您可以使用 -c 运行 django shell,它将运行您传递的命令,但是在代码运行后它会立即退出。

诀窍是设置您需要的内容,运行 code.interact(local=locals()) 然后从您传递的代码中重新启动 shell。像这样:

python manage.py shell -c 'import uuid;test="mytestvar";import code;code.interact(local=locals())'

对我来说,我只想要丰富库的检查方法。只有几行:

python manage.py shell -c 'import code;from rich import pretty;pretty.install();from rich import inspect;code.interact(local=locals())'

最后上面的樱桃是一个别名

alias djshell='python manage.py shell -c "import code;from rich import pretty;pretty.install();from rich import inspect;code.interact(local=locals())"'

现在,如果我启动我的 shell 并说,想要检查表单类,我会得到这个漂亮的输出: 在此处输入图像描述

于 2020-12-19T13:05:52.660 回答
1

您可以像这样设置管理命令并每次重新运行,而不是从 Django shell 运行命令。

于 2013-12-03T09:48:57.677 回答
1

不完全是您想要的,但我现在倾向于构建自己的管理命令来测试和摆弄事物。

在命令中,您可以按照您想要的方式设置一堆本地变量,然后放入交互式 shell。

import code

class Command(BaseCommand):
  def handle(self, *args, **kwargs):
     foo = 'bar'
     code.interact(local=locals())

无需重新加载,而是一种简单且不那么烦人的交互式测试 django 功能的方法。

于 2013-12-11T08:06:22.373 回答