Opened 9 years ago

Closed 9 years ago

Last modified 9 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

Description

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 by Anssi Kääriäinen, 9 years ago

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 by Tom Christie, 9 years ago

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 9 years ago by Tom Christie (previous) (diff)

comment:3 by Tim Graham, 9 years ago

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

comment:4 by Collin Anderson, 9 years ago

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 by Tim Graham, 9 years ago

Has patch: set

comment:6 by Markus Holtermann, 9 years ago

Triage Stage: AcceptedReady for checkin

comment:7 by Tim Graham <timograham@…>, 9 years ago

Resolution: fixed
Status: newclosed

In 888054bff7c5878e026bac2e712d5480f7e295c7:

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

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

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