How to reload modules in django shell?

Viewed 54280

I am working with Django and use Django shell all the time. The annoying part is that while the Django server reloads on code changes, the shell does not, so every time I make a change to a method I am testing, I need to quit the shell and restart it, re-import all the modules I need, reinitialize all the variables I need etc. While iPython history saves a lot of typing on this, this is still a pain. Is there a way to make django shell auto-reload, the same way django development server does?

I know about reload(), but I import a lot of models and generally use from app.models import * syntax, so reload() is not much help.

12 Answers

Use shell_plus with an ipython config. This will enable autoreload before shell_plus automatically imports anything.

pip install django-extensions
pip install ipython
ipython profile create

Edit your ipython profile (~/.ipython/profile_default/ipython_config.py):

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

Open a shell - note that you do not need to include --ipython:

python manage.py shell_plus

Now anything defined in SHELL_PLUS_PRE_IMPORTS or SHELL_PLUS_POST_IMPORTS (docs) will autoreload!

Note that if your shell is at a debugger (ex pdb.set_trace()) when you save a file it can interfere with the reload.

Using a combination of 2 answers for this I came up with a simple one line approach.

You can run the django shell with -c which will run the commands you pass however it quits immediately after the code is run.

The trick is to setup what you need, run code.interact(local=locals()) and then re-start the shell from within the code you pass. Like this:

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

For me I just wanted the rich library's inspect method. Only a few lines:

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

Finally the cherry on top is an alias

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

Now if I startup my shell and say, want to inspect the form class I get this beautiful output: enter image description here

Instead of running commands from the Django shell, you can set up a management command like so and rerun that each time.

import test  // test only has x defined
test.x       // prints 3, now add y = 4 in test.py
test.y       // error, test does not have attribute y

solution Use reload from importlib as follows

from importlib import reload
import test // test only has x defined
test.x // prints 3, now add y = 4 in test.py
test.y // error
reload(test)
test.y // prints 4
Related