Code

Opened 8 years ago

Closed 7 years ago

#2684 closed defect (worksforme)

[patch] Backwards relations (ie. xxx_set) across different apps needs voodoo magic to work

Reported by: parlar@… Owned by: oggie_rob
Component: Core (Other) Version: master
Severity: normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: UI/UX:

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)

2684.patch (1.2 KB) - added by russellm 8 years ago.
Patch to force caching of related objects

Download all attachments as: .zip

Change History (9)

comment:1 Changed 8 years ago by parlar@…

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!

Changed 8 years ago by russellm

Patch to force caching of related objects

comment:2 Changed 8 years ago by russellm

  • Owner changed from adrian to russellm
  • Status changed from new to assigned
  • Summary changed from Backwards relations (ie. xxx_set) across different apps needs voodoo magic to work to [patch] Backwards relations (ie. xxx_set) across different apps needs voodoo magic to work
  • Version set to SVN

The attached patch fixes the problem; commit pending the lifting of the moratorium on django.db.models development.

comment:3 Changed 8 years ago by russellm

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 Changed 8 years ago by russellm

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:5 Changed 8 years ago by mtredinnick

Looks like #2416 contains another side-effect of this.

comment:6 Changed 7 years ago by SmileyChris

  • Patch needs improvement set
  • Triage Stage changed from Unreviewed to Accepted

comment:7 Changed 7 years ago by oggie_rob

  • Owner changed from nobody to oggie_rob
  • Status changed from assigned to 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 Changed 7 years ago by russellm

  • Resolution set to worksforme
  • Status changed from new to closed

Looks like this problem has been fixed by the model loading refactor.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.