Opened 5 years ago

Closed 5 years ago

#20378 closed Bug (fixed)

Reverse join fails when GenericRelation is defined on an abstract model

Reported by: gwahl@… Owned by: Anssi Kääriäinen
Component: contrib.contenttypes Version: master
Severity: Release blocker Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


When you define a GenericRelation on an abstract model:

class HasLinks(models.Model):
    links = generic.GenericRelation(Link)

    class Meta:
        abstract = True

class HasLinkThing(HasLinks):

You should still be able to query using the reverse join:


But it fails with when trying to calculate the join columns, because it's trying to get the pk of the abstract, instead of concrete, model:

Traceback (most recent call last):
  File ".tox/py27-dj16/src/django/tests/generic_relations_regress/", line 145, in test_abstract_reverse_join
    self.assertQuerysetEqual(HasLinkThing.objects.filter(links=link), [
  File ".tox/py27-dj16/src/django/django/db/models/", line 163, in filter
    return self.get_queryset().filter(*args, **kwargs)
  File ".tox/py27-dj16/src/django/django/db/models/", line 661, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File ".tox/py27-dj16/src/django/django/db/models/", line 679, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File ".tox/py27-dj16/src/django/django/db/models/sql/", line 1200, in add_q
    clause = self._add_q(where_part, used_aliases)
  File ".tox/py27-dj16/src/django/django/db/models/sql/", line 1236, in _add_q
  File ".tox/py27-dj16/src/django/django/db/models/sql/", line 1102, in build_filter
  File ".tox/py27-dj16/src/django/django/db/models/sql/", line 1365, in setup_joins
    connection = alias, opts.db_table, join.join_field.get_joining_columns()
  File ".tox/py27-dj16/src/django/django/db/models/fields/", line 862, in get_joining_columns
    return self.field.get_reverse_joining_columns()
  File ".tox/py27-dj16/src/django/django/db/models/fields/", line 1009, in get_reverse_joining_columns
    return self.get_joining_columns(reverse_join=True)
  File ".tox/py27-dj16/src/django/django/contrib/contenttypes/", line 199, in get_joining_columns
    return super(GenericRelation, self).get_joining_columns(reverse_join)
  File ".tox/py27-dj16/src/django/django/db/models/fields/", line 1005, in get_joining_columns
    source = self.reverse_related_fields if reverse_join else self.related_fields
  File ".tox/py27-dj16/src/django/django/db/models/fields/", line 980, in reverse_related_fields
    return [(rhs_field, lhs_field) for lhs_field, rhs_field in self.related_fields]
  File ".tox/py27-dj16/src/django/django/db/models/fields/", line 975, in related_fields
    self._related_fields = self.resolve_related_fields()
  File ".tox/py27-dj16/src/django/django/contrib/contenttypes/", line 178, in resolve_related_fields
    self.to_fields = []
AttributeError: 'NoneType' object has no attribute 'name'

I've written a failing test to demonstrate: This test passes in django 1.5.1, but fails on master, so I believe this is a regression introduced by #19385.

Change History (2)

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

Owner: changed from nobody to Anssi Kääriäinen
Severity: NormalRelease blocker
Status: newassigned
Triage Stage: UnreviewedAccepted

Seems like a release blocker. I will try to fix this as soon as possible, but unfortunately I don't have time in the next two weeks. So, if anybody else wants to try to fix this feel free to do so...

comment:2 Changed 5 years ago by Anssi Kääriäinen <akaariai@…>

Resolution: fixed
Status: assignedclosed

In c9a96075fa02b6d52bec748ffdfb413688a15774:

Fixed #20378 -- regression in GenericRelation on abstract model

When a GenericRelation was defined on abstract model, queries on childs
of the abstract model didn't work. The problem was in the way fields and
in particular field.rel was copied from models to their children.

The regression was likely caused by #19385. Thanks to Gavin Wahl for
spotting the regression.

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