Opened 8 months ago

Closed 8 months ago

Last modified 8 months ago

#22992 closed Bug (fixed)

"'GenericForeignKey' object has no attribute 'get_lookup'" exception on 1.7

Reported by: glicerinu@… Owned by: nobody
Component: contrib.contenttypes Version: 1.7-rc-1
Severity: Release blocker Keywords: contenttypes GenericForeignKey get_lookup
Cc: 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

Current 1.7 breaks querying by content_object on a model with generic relations.

>>> MonitorData.objects.get(content_object=site)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 92, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 345, in get
    clone = self.filter(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 689, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 707, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 1287, in add_q
    clause, require_inner = self._add_q(where_part, self.used_aliases)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 1314, in _add_q
    current_negated=current_negated, connector=connector)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 1186, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 1092, in build_lookup
    final_lookup = lhs.get_lookup(lookup)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/datastructures.py", line 25, in get_lookup
    return self.output_field.get_lookup(name)
AttributeError: 'GenericForeignKey' object has no attribute 'get_lookup'

MonitorData looks like:

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType

class MonitorData(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    value = models.PositiveIntegerField()
    
    content_object = GenericForeignKey()

Attachments (1)

22992-test.diff (605 bytes) - added by timo 8 months ago.

Download all attachments as: .zip

Change History (8)

comment:1 Changed 8 months ago by timo

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

From the docs (right above this section):

Due to the way GenericForeignKey is implemented, you cannot use such fields directly with filters (filter() and exclude(), for example) via the database API. Because a GenericForeignKey isn’t a normal field object, these examples will not work:

# This will fail
>>> TaggedItem.objects.filter(content_object=guido)
# This will also fail
>>> TaggedItem.objects.get(content_object=guido)

When I try your example, I get FieldError: Cannot resolve keyword 'content_object' into field. Choices are: content_type, id, object_id, value. Am I missing something? Did your test work in older versions? I got the same result on 1.6.

Edit: Actually, I get FieldError on 1.6, but AttributeError: 'GenericForeignKey' object has no attribute 'get_lookup' as you described on 1.7. Will bisect...

Last edited 8 months ago by timo (previous) (diff)

comment:2 Changed 8 months ago by timo

  • Triage Stage changed from Unreviewed to Accepted

comment:3 Changed 8 months ago by glic3rinu

Yes, you're right this is not a bug.

Before reporting I skimmed the docs and found the "guido" example, but not reading carefully enough to realize it was actually saying it wasn't possible!

Sorry for wasting your time Timo !

Changed 8 months ago by timo

comment:4 Changed 8 months ago by timo

Added a test that passes on 1.6 but fails on master & 1.7.

comment:5 Changed 8 months ago by timo

  • Has patch set
  • Triage Stage changed from Accepted to Ready for checkin

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

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

In efe87d3e48df9b7470a3006eeb7322f12b368fdf:

Fixed #22992 -- regression in .filter(generic_fk=...) error message

Generic Foreign Keys can't be used as lhs in lookups for historical
reasons. Django 1.6 gave a FieldDoesNotExist exception when using GFKs
as lhs in lookups, but due to regression caused by lookup refactor patch
(20bab2cf9d02a5c6477d8aac066a635986e0d3f3) the exception type was
changed to AttributeError.

It might be a good idea to add support for gfkexact and gfkin lookups
later on.

Thanks to glicerinu@… for the report. The code in this commit
was written by Tim Graham.

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

In 4b53bfff3714d1f6f0f830d56fff296fb57b21da:

[1.7.x] Fixed #22992 -- regression in .filter(generic_fk=...) error message

Generic Foreign Keys can't be used as lhs in lookups for historical
reasons. Django 1.6 gave a FieldDoesNotExist exception when using GFKs
as lhs in lookups, but due to regression caused by lookup refactor patch
(20bab2cf9d02a5c6477d8aac066a635986e0d3f3) the exception type was
changed to AttributeError.

It might be a good idea to add support for gfkexact and gfkin lookups
later on.

Thanks to glicerinu@… for the report. The code in this commit
was written by Tim Graham.

Backport of efe87d3e48 from master

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