Opened 18 years ago
Closed 17 years ago
#2684 closed defect (worksforme)
[patch] Backwards relations (ie. xxx_set) across different apps needs voodoo magic to work
Reported by: | Owned by: | oggie_rob | |
---|---|---|---|
Component: | Core (Other) | Version: | dev |
Severity: | normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
As described (and temporarily solved) here: http://groups.google.com/group/django-users/browse_frm/thread/8b1f9699dd5c72d1/2663f422db6a027c?lnk=arm#2663f422db6a027c
In general, I have a Photo model and an Article model. They live in separate applications. The Article model has:
picture = models.ForeignKey(Photo)
The problem is that you can't access the 'article_set' attribute from a Photo instance *unless* you've already imported 'Article'.
Russell says that this is reasonably obvious if you know the internals, but it's definitely not documented.
So this should be properly documented, and if anyone can figure out how, a fix should be put in so you don't need to import the 'Article' model just to be able to access 'article_set' on a Photo instance.
Attachments (1)
Change History (9)
comment:1 by , 18 years ago
comment:2 by , 18 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Summary: | Backwards relations (ie. xxx_set) across different apps needs voodoo magic to work → [patch] Backwards relations (ie. xxx_set) across different apps needs voodoo magic to work |
Version: | → SVN |
The attached patch fixes the problem; commit pending the lifting of the moratorium on django.db.models development.
comment:3 by , 18 years ago
To clarify the exact problem; If you have a model A with a ForiegnKey/M2M relation on model B, and your code is:
from test.project.models import B objs = B.objects.all()
the members of objs
don't have their related descriptors (e.g., b.a_set) instantiated. This is because the related models are never imported, so the
contribute_to_class
methods for the related classes are never called.
A single call to B.objects.get()
,
B.objects.filter()
, or just about anything else that interacts with fields will call the
_meta.get_all_related_objects()
and
_meta.get_all_related_many_to_many_objects()
methods to be called, which causes these methods to fill their caches, which causes the related models to be imported, and the related descriptors to be created.
Simple workaround, demonstrated in the patch - force the creation of an object instance to cause the meta class instance to populate its caches.
comment:4 by , 18 years ago
I should clarify - this isn't anywhere close to an ideal fix; I'm actually against applying it to trunk. However, it is a rough workaround, and gives a vague indication where the problem lies.
comment:6 by , 18 years ago
Patch needs improvement: | set |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:7 by , 17 years ago
Owner: | changed from | to
---|---|
Status: | assigned → new |
I think this can be closed now. I tested it out and it seems to work without importing the backward-related field.
comment:8 by , 17 years ago
Resolution: | → worksforme |
---|---|
Status: | new → closed |
Looks like this problem has been fixed by the model loading refactor.
Update:
If you do the following:
'Photo.objects.all()[0].article_set.all()' without importing 'Article', you will get an AttributeError on 'article_set'.
However, if you do this instead:
'Photo.objects.get(id=1).article_set.all()' without importing 'Article', the 'article_set' attribute works perfectly!