Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#29653 closed Bug (fixed)

Using GenericRelation.related_query_name through an inherited abstract class crashes

Reported by: Lauri Kainulainen Owned by: Ramiro Morales
Component: contrib.contenttypes Version: 2.1
Severity: Release blocker Keywords:
Cc: robwa Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

We upgraded a production app from 1.10 to 2.1.0 today and ran into an interesting issue. Our previous models (trimmed for readability):

class Event(models.Model):
    class Meta:
        ordering = ['time']
    target_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    target_id = models.PositiveIntegerField()
    target = GenericForeignKey('target_type', 'target_id')
    time = models.DateTimeField()

class EventTarget(models.Model):
    class Meta:
        abstract = True
    events = GenericRelation(Event, 'target_id', 'target_type', related_query_name='targets')
    
class WorkOrder(EventTarget):
     [...]

Worked fine previously, but in Django 2 we got this:

In [1]: from workorders.models import *

In [2]: e = WorkOrder.objects.first().events.first()

In [3]: e.targets
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-cc5f08905ab7> in <module>()
----> 1 e.targets

AttributeError: 'Event' object has no attribute 'targets'

If we move the GenericRelation directly inside the model it works:

[...]
class WorkOrder(models.Model):
    events = GenericRelation(Event, 'target_id', 'target_type', related_query_name='targets')
[...]    
In [1]: from workorders.models import *

In [2]: e = WorkOrder.objects.first().events.first()

In [3]: e.targets
Out[3]: <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager at 0x7f5f9df2af60>

Change History (6)

comment:1 by Tim Graham, 6 years ago

Cc: robwa added
Severity: NormalRelease blocker
Summary: Using GenericRelation.related_query_name through an inherited abstract class breaks when upgrading from django 1.10 to 2.1.0Using GenericRelation.related_query_name through an inherited abstract class crashes
Triage Stage: UnreviewedAccepted

comment:2 by Ramiro Morales, 6 years ago

Additionally, the test case added in the commit which introduced the regression (4ab027b94409e6415b774797bf9d3593da9d9ea8 to fix #28988) isn't actually testing the originally reported scenario. The Place model containig the GeneridRelation field isn't using MTI.

in reply to:  2 comment:3 by Ramiro Morales, 6 years ago

Owner: changed from nobody to Ramiro Morales
Status: newassigned

Replying to Ramiro Morales:

Additionally, the test case added in the commit which introduced the regression (4ab027b94409e6415b774797bf9d3593da9d9ea8 to fix #28988) isn't actually testing the originally reported scenario. The Place model containig the GeneridRelation field isn't using MTI.

Scrap this comment. I misread the #28988 ticket.

comment:4 by Ramiro Morales, 6 years ago

Has patch: set

comment:5 by Tim Graham <timograham@…>, 6 years ago

Resolution: fixed
Status: assignedclosed

In b5c7cb4d:

Fixed #29653 -- Fixed missing related_query_name reverse accessor if GenericRelation is declared on an abstract base model.

Regression in 4ab027b94409e6415b774797bf9d3593da9d9ea8.

Thanks Lauri Kainulainen for the report.

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

In f72a7d8f:

[2.1.x] Fixed #29653 -- Fixed missing related_query_name reverse accessor if GenericRelation is declared on an abstract base model.

Regression in 4ab027b94409e6415b774797bf9d3593da9d9ea8.

Thanks Lauri Kainulainen for the report.

Backport of b5c7cb4d3306a7b4e8f87bcf365ff30ae53018ed from master

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