How do you reload a Django model module using the interactive interpreter via "manage.py shell"?

Solution 1:

Well, I think I have to answer to this. The problem is that Django caches its models in a singleton (singleton like structure) called AppCache. Basically, to reload Django models you need to first reload and re-import all the model modules stored in the AppCache. Then you need to wipe out the AppCache. Here's the code for it:

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

I've put all of this in a separate file called reloadmodels.py in the root directory of my Django site. Using IPython I can reload everything by running:

%run ~/mysite/reloadmodels.py

Solution 2:

My solution on 2016 (in future it may be changed)

1.Install django_extension

2.Add next settings:

SHELL_PLUS = 'ipython'

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

3.Run shell

./manage.py shell_plus

See results:

model example

class Notification(models.Model):

    ........

    @classmethod
    def get_something(self):

        return 'I am programmer'

In shell

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

Made changes on model

@classmethod
    def get_something(self):

        return 'I am Python programmer'

In shell

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

In shell. This is a magic

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

In shell

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

Made changes again

    @classmethod
    def get_something(self):

        return 'I am full-stack Python programmer'

In shell

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

Drawback: 1. Need manually run code

%autoreload 2

since django_extension 1.7 has not support for run arbitrary code. May be in future release it has this feature.

Notes:

  1. Django 1.10
  2. Python 3.4
  3. django_extension 1.7.4
  4. Based (primary) on https://django-extensions.readthedocs.io/en/latest/shell_plus.html and http://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html
  5. Caution. It is may be produce an error, if you try change a code where used super().

Solution 3:

You can also use django-extensions project with the following command:

manage.py shell_plus --notebook

This will open a IPython notebook on your web browser instead of the IPython shell interpreter. Write your code there, and run it.

When you change your modules, just click on the web page menu item 'Kernel->Restart'

Re-running the code now uses your modified modules.

Solution 4:

Assuming your project is set up this way

  • project name : bookstore
  • app name : shelf
  • model name : Books

first load

from bookstore.shelf.models import Books

subsequent reloads

import bookstore;reload(bookstore.shelf.models);from bookstore.shelf.models import Books