Opened 12 years ago
Closed 11 years ago
#18907 closed Bug (fixed)
Documentation regarding population of backrefs is incorrect
Reported by: | Simon Percivall | Owned by: | |
---|---|---|---|
Component: | Documentation | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | ke1g, percivall@… | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
It is stated at https://docs.djangoproject.com/en/1.4/topics/db/queries/#how-are-the-backward-relationships-possible in the third paragraph that "the first time any model is loaded" Django iterates INSTALLED_APPS
and populates backrefs. Either this is plain wrong, or the text needs clarification.
- I create a minimal two-app project where app2.Model2 has a reference to app1.Model1 and both
app1
andapp2
are inINSTALLED_APPS
- I create a Model1:
Model1.objects.create()
- I write and run a script:
from app1.models import Model1 m = Model1.objects.get().model2s.all()
- and get
Traceback (most recent call last): File "f.py", line 8, in <module> Model1.objects.get().model2s.all() AttributeError: 'Model1' object has no attribute 'model2s'
If I add import app2.models
, it'll work.
Change History (9)
comment:1 by , 12 years ago
Cc: | added |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 12 years ago
When running Django in a larger project, with something like mod_wsgi or gunicorn instead of runserver, and with Celery or other jobs doing background processing, models are also not auto-loaded, unless, as you say, they're loaded as a side-effect of other operations.
Changing the text to say "under normal operation", therefore, is deeply misleading.
I hesitated whether to submit this as a documentation issue or as a core bug. It might be argued that population of backrefs is a guarantee that Django actually should make. From my perspective, that would probably be the preferred solution.
comment:3 by , 12 years ago
Cc: | added |
---|
comment:4 by , 12 years ago
Type: | Uncategorized → Bug |
---|
comment:5 by , 11 years ago
@augustin, has this behavior been rectified with the app loading changes in 1.7? If not, I wonder if you could briefly describe the current behavior so I could write up a patch (assuming you don't want to do so yourself).
comment:6 by , 11 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:7 by , 11 years ago
Tim, here's a proposal to replace the third paragraph of "How are the backward relationships possible?".
If you can improve the wording and commit it, that's perfect. Thank you!
The answer lies in the app registry. When Django starts, it imports each application listed in :setting:`INSTALLED_APPS`, and then the ``models`` module inside each application. Whenever a new model class is created, Django adds backward-relationships to related models. If the related models haven't been imported yet, Django keeps tracks of the relationships and adds them when the related models eventually are imported. For this reason, it's particularly important that all the models you're using be defined in applications listed in :setting:`INSTALLED_APPS`. Otherwise, backwards relations may not work properly.
comment:8 by , 11 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:9 by , 11 years ago
Owner: | set to |
---|---|
Resolution: | → fixed |
Status: | new → closed |
I know, from time spent with pdb searching for import order problems, that the documentation is wrong.
While there can be things in a models.py that trigger all installed apps to load, such as the use of non-lazy internationalization, many models.py files don't trigger general loading. In production the usual place that the installed apps are all loaded is in admin.autodiscover() called from the ROOT_URL_CONF, which gets imported at the first request. Under runserver, it happens sooner, during the model "validation" that runserver does explicitly. shell and some of the other management commands are not going to do it.
This might almost be a white lie, if the tutorial didn't encourage the novice to play with models in the shell.
Perhaps change "The first time any model is loaded," to "Under normal operation", and append a comment, maybe in parentheses, that "There may be times, such as when using the manage.py shell, when you must import models from more than the app of interest in order to have the reverse relationships connected."