Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#24208 closed Cleanup/optimization (fixed)

Change in `get_all_related_objects` behavior.

Reported by: Tom Christie Owned by: nobody
Component: Documentation Version: 1.8alpha1
Severity: Release blocker Keywords:
Cc: Tom Christie, cmawebsite@… Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


In Django 1.8 alpha, the behavior of the internal get_all_related_objects() changes.

If I have a model with a reverse foreign key relationship then...

  • In 1.7 get_all_related_objects returns the relationship as django.db.models.related.RelatedObject with the model attribute set to the source of the relationship.
  • In 1.8-alpha get_all_related_objects returns the relationship as django.db.models.fields.related.ManyToOneRel with the model attribute set to the target of the relationship.

Effect is that for REST framework ModelSerializers any automatic reverse relationships will be incorrectly generated.

This is private API, but it's also currently API that third party apps do need to rely on in order to be able to function and correctly introspect the model relationships.

I'd also be okay with a resolution where this *isn't* fixed per-se, but that it is at least demonstrated that there's now an alternative route that I can use to correctly determine the reverse relationships.

Change History (8)

comment:1 Changed 8 years ago by Anssi Kääriäinen

Triage Stage: UnreviewedAccepted

The likely reason for this regression is that field.rel.model was defined differently from field.related.model. After removal of RelatedObject field.related is just a property that returns field.rel. Also, get_all_related_objects() used to return field.related, but now it likely returns field.rel instances.

I see a couple of approaches to solve this issue:

  1. Create a proxy object for field.related (or do this only for the return value of get_all_related_objects()). This object should then return the correct model as RelatedObject used to do.
  2. Document a way to conditionally access a different property from the field.rel ManyToOneRel instance which returns the correct model instance.

I think approach 1. is preferable. It should be easy to do so, and the field.related API is deprecated, so we get to remove the proxy object in a couple of releases.

comment:2 Changed 8 years ago by Tom Christie

Triage Stage: AcceptedUnreviewed

Workaround - .related_model will return the source model, so...

    for relation in opts.get_all_related_objects():
        to_model = getattr(relation, 'related_model', relation.model)

Appears to work consistently across Django versions.

Last edited 8 years ago by Tom Christie (previous) (diff)

comment:3 Changed 8 years ago by Tim Graham

Component: Database layer (models, ORM)Documentation
Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization

comment:4 Changed 8 years ago by Collin Anderson

Cc: cmawebsite@… added

Yes, this was a backwards-incompatible decision we made, but it needs to be documented.

I think we should document the getattr() approach. I've ran into this issue with contribute_to_related_class and used the getattr() approach.

comment:5 Changed 8 years ago by Tim Graham

Has patch: set

comment:6 Changed 8 years ago by Markus Holtermann

Triage Stage: AcceptedReady for checkin

comment:7 Changed 8 years ago by Tim Graham <timograham@…>

Resolution: fixed
Status: newclosed

In 888054bff7c5878e026bac2e712d5480f7e295c7:

Fixed #24208 -- Documented changes in private model relations.

comment:8 Changed 8 years ago by Tim Graham <timograham@…>

In 28bb0ad19947514cd275e5692a5424e45919b5be:

[1.8.x] Fixed #24208 -- Documented changes in private model relations.

Backport of 888054bff7c5878e026bac2e712d5480f7e295c7 from master

Note: See TracTickets for help on using tickets.
Back to Top