Hello,
Until Django 1.3 introduced the current project layout, every Django project was vulnerable to double import problems: since PYTHONPATH contained both a directory and its parent, the same module could get imported twice through different paths.
For more information on why this is a problem, I’ll defer to Nick Coghlan’s excellent explanation:
http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html#the-double-import-trap
As of Django 1.6, there’s no built-in support for setting PYTHONPATH like that. However, some users may still be setting it manually to avoid fixing their imports.
Besides, Django still contains some ad-hoc mechanisms to work around the consequences of this poor setup, notably:
- fragile behavior in ModelBase, the metaclass for Model: defining a class that inherits from Model can return an existing class instead of creating a new one, which doesn’t play well with decorators (see #21733 for an interesting example),
- the dispatch_uid argument of signals,
- etc.
As part of the app-loading refactor, I’d like to remove that behavior in ModelBase. This will prevent importing models twice through different paths. This is backwards-incompatible: it will force users relying on double imports to refactor their imports.
Considering that:
- double imports are arguably an incorrect setup — it’s unfortunate Django did it for so long,
- fixing them a purely mechanical refactoring (replace-all) that shouldn’t take much time even on large codebases,
- this change will make further app-loading improvements possible,
I’m inclined to do it immediately.
However, if the majority thinks this isn’t acceptable, I’ll create a deprecation path and defer further cleanup of ModelBase.__new__ to Django 1.9.
What do you think?
--
Aymeric.