Opened 15 years ago

Closed 10 years ago

#11264 closed Bug (invalid)

"from django.db import models" clobbered in functions inside __init__.py of installed apps

Reported by: Antti Kaihola Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords: importing
Cc: miracle2k Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Ramiro Morales)

If an app myapp has the following __init__.py:

from django.db import models
def myfunc():
    assert models.__package__ == 'django.db.models', (
        'models is %r instead of django.db.models' % models)

then calling myapp.myfunc() throws:

AssertionError:
  models is <module 'myapp.models' from 'myapp/models.pyc'>
  instead of django.db.models

This happens only if

  • myapp is in INSTALLED_APPS
  • myfunc is in myapp/__init__.py, not some other module in it
  • Django is r10088 or later (thanks, git bisect)

This breaks at least Satchmo from a few months back for me, probably trunk too.

r10088 claims to have fixed all dynamic imports in Django by backporting importlib from Python 2.7.

Attachments (1)

11264_models_clobber_test_project.zip (2.6 KB ) - added by Antti Kaihola 15 years ago.
a minimal test project to reproduce "models" clobbering

Download all attachments as: .zip

Change History (10)

by Antti Kaihola, 15 years ago

a minimal test project to reproduce "models" clobbering

in reply to:  description comment:1 by Antti Kaihola, 15 years ago

Replying to akaihola:

Messed up the assertion error -- for myapp it's of course

AssertionError:
  models is <module 'myapp.models' from 'myapp/models.pyc'>
  instead of django.db.models

So what happens is that inside the function models points to the app's own models.py instead of django.db.models.

comment:2 by Antti Kaihola, 15 years ago

The issue this causes in Satchmo was reported in a thread on the Satchmo users Google Group.

comment:3 by Russell Keith-Magee, 15 years ago

Triage Stage: UnreviewedAccepted

Some extra debug: If your test case invokes

import myapp
myapp.myfunc()

or

import myapp
from myapp import model
myapp.myfunc()

everything works as expected. It's only when you run

import myapp
from myapp.models import *
myapp.myfunc()

that you get a problem.

comment:4 by miracle2k, 15 years ago

Cc: miracle2k added

comment:5 by Julien Phalip, 14 years ago

Severity: Normal
Type: Bug

comment:6 by Ramiro Morales, 13 years ago

Description: modified (diff)
Easy pickings: unset
UI/UX: unset

comment:7 by Aymeric Augustin, 12 years ago

This bug still exists in master.

After adjusting settings.py and manage.py for Django 1.6 in the test project, I was able to reproduce it:

>>> import models_clobber_test_app
>>> models_clobber_test_app.assert_models_package()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/myk/Documents/dev/django/models_clobber_test_project/models_clobber_test_app/__init__.py", line 11, in assert_models_package
    'models is %r instead of django.db.models' % models)
AssertionError: models is <module 'models_clobber_test_app.models' from '/Users/myk/Documents/dev/django/models_clobber_test_project/models_clobber_test_app/models.py'> instead of django.db.models

comment:8 by Aymeric Augustin, 12 years ago

Component: Core (Other)Database layer (models, ORM)

comment:9 by Aymeric Augustin, 10 years ago

Resolution: invalid
Status: newclosed

It turns out that this has nothing to do with Django. This surprising behavior can be reproduced with plain Python modules.

% cat foo/__init__.py

bar = 42

def print_bar():
    print(bar)

% cat foo/bar.py

# Empty module.

% python

>>> from foo import print_bar
>>> print_bar()
42
>>> import foo.bar
>>> print_bar()
<module 'foo.bar' from 'foo/bar.py'>
Note: See TracTickets for help on using tickets.
Back to Top