tags:

views:

1933

answers:

4

I know how to reload a regular Python module within a regular Python interpreter session. This question documents how to do that pretty well:

How do I unload (reload) a Python module?

For some reason, I am having trouble doing that within Django's "manage.py shell" interpreter session. To recreate my issue, start the basic Django tutorial found here:

Writing your first Django app, part 1

After creating the "polls" application and "Poll" class, start up the interpreter via "manage.py shell" and import the "polls" app into it.

import polls.models as pm

Create a new "Poll" object:

p = pm.Poll()

All is well and good so far. Now go back to your source and add any arbitrary method or attribute. For example, I've added:

def x(self):
    return 2+2

Now go back to the interpreter and "reload" the module:

reload(pm)

Now try to use your new method or attribute:

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

You'll get this message:

'Poll' object has no attribute 'x'

What gives? I've also tried rerunning the import command, importing the module using different syntax, deleting all references to any "Poll" objects or to the "Poll" class. I've also tried this with both the IPython interpreter and with the plain Python (v2.6) interpreter. Nothing seems to work.

Using the same techniques with an arbitrary Python module in a regular interpreter session works perfectly. I just can't seem to get it to work in Django's "shell" session.

By the way, if it makes any difference, I'm doing this on a Ubuntu 9.04 machine.

A: 

ipython console does a deep reload with each reload() expression; and of course adds a lot of other useful stuff.

Lakshman Prasad
After trying that, a separate issue pops up. I get a ImportError: No module named django.models
Chad Braun-Duin
Ubuntu 9.04 has Python2.6 as the latest version. U need to enter command python2.5 manage.py runserver. (If U installed django via easy_install, ensure you install it on python2.5 installation)
Lakshman Prasad
dreload(<djangomodule>) using python2.5 manage.py runserver gives the same ImportError
Chad Braun-Duin
+5  A: 

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:

from django.db.models.loading import AppCache
cache = AppCache()

for app in cache.get_apps():
    __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
Chad Braun-Duin
+2  A: 

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
surtyaar
+2  A: 

As far as I'm concerned, none of the above solutions worked on their own, also this thread didn't help much on its own, but after combining the approaches I managed to reload my models in shell_plus:

  1. Make changes to the model (MyModel)
  2. remove models.pyc
  3. Clean Django model cache (like here):

     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
    
  4. Reload model like here

    reload(project.app.models)
    from project.app.models import MyModel
    
Tomasz Zielinski