Kit Sunde
Kit Sunde

Reputation: 37095

Removing the mysite prefix from INSTALLED_APPS in "mysite.app" prevents double imports, why?

I ran into the issue where post_save was being called twice for no apparent reason. It now seems that the cause was a double import as described here: Why is post_save being raised twice during the save of a Django model? the accept answer suggest removing the mysite portion of mysite.foo which worked, but why does it do a double import?

Upvotes: 4

Views: 187

Answers (1)

okm
okm

Reputation: 23871

The issue is caused by mixing import paths in Python. Take the following structure w/ proj findable in sys.path, for example.

proj/
   __init__.py
   app/
       __init__.py
       foo.py

# In proj directory, enter Python shell
>>> import sys

>>> before = set(sys.modules)
>>> import app.foo
>>> set(sys.modules) - before
set(['app', 'app.foo'])

>>> before = set(sys.modules)
>>> from proj.app import foo
>>> set(sys.modules) - before
set(['proj.app.foo', 'proj', 'proj.app'])

Python actually treats proj.app.foo and app.foo as different modules. You could find that app/__init__.py and app/foo.py get imported twice, thus anything in them actually get executed twice. To fix this, we should use consistent import path: either from proj level or from ../proj level. In the link you posted, 'mysite.blog' is fine AS LONG AS there is no other importing like import blog in the project or Django files.

In Django 1.4, the issue is mostly solved by moving manage.py one directory up from project directory to its parent directory which is no longer a package, thus limit importing to proj level.

Also you could prevent duplicate signals by using dispatch_uid

Upvotes: 3

Related Questions