Opened 4 years ago

Last modified 18 months ago

#12885 new Bug

GenericRelation fails to join the related table from a inherited model

Reported by: semenov Owned by: nobody
Component: contrib.contenttypes Version: 1.1
Severity: Normal Keywords:
Cc: carljm Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


A minimalistic crashing example is worth thousands words:

class Car(models.Model):
        content_type = models.ForeignKey(ContentType)
        object_id = models.PositiveIntegerField()
        object = generic.GenericForeignKey()

class CarDriver(models.Model):
        cars = generic.GenericRelation(Car)

class Truck(Car):

class TruckDriver(models.Model):
        trucks = generic.GenericRelation(Truck)

# Selecting cars for a car drivers works fine

>>> john = CarDriver.objects.create()
>>> Car.objects.filter(cardriver=john)

# Selecting trucks for a truck driver crashes

>>> pete = TruckDriver.objects.create()
>>> Truck.objects.filter(truckdriver=pete)
# OperationalError: (1054, "Unknown column 'T2.object_id' in 'where clause'")

Attachments (0)

Change History (12)

comment:1 Changed 4 years ago by carljm

  • Cc carljm added
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 4 years ago by ramiro

  • Component changed from ORM aggregation to Database layer (models, ORM)
  • Owner set to nobody

Can you exercise the same test case you've created against SVN trunk and report back the results please?

comment:3 Changed 4 years ago by semenov

The SQL query is a bit different in SVN trunk, but still results in the same error ("Unknown column 'T2.object_id' in 'where clause'").

SQL query in Django 1.1.1:

SELECT `tracker_car`.`id`, `tracker_car`.`content_type_id`, `tracker_car`.`object_id`, `tracker_truck`.`car_ptr_id`
FROM `tracker_truck`
INNER JOIN `tracker_truck` T2 ON (`tracker_truck`.`car_ptr_id` = T2.`id`)
INNER JOIN `tracker_car` ON (`tracker_truck`.`car_ptr_id` = `tracker_car`.`id`)
WHERE T2.`object_id` = 1 LIMIT 21

SQL query in Django-SVN r12453:

SELECT `tracker_car`.`id`, `tracker_car`.`content_type_id`, `tracker_car`.`object_id`, `tracker_truck`.`car_ptr_id`
FROM `tracker_truck`
INNER JOIN `tracker_truck` T2 ON (`tracker_truck`.`car_ptr_id` = T2.`car_ptr_id`)
INNER JOIN `tracker_car` ON (`tracker_truck`.`car_ptr_id` = `tracker_car`.`id`)
WHERE T2.`object_id` = 1 LIMIT 21

(By the way, I am also confused by the magic number 21, but that's irrelevant to the topic.)

comment:4 Changed 4 years ago by russellm

  • Triage Stage changed from Unreviewed to Accepted

comment:5 Changed 4 years ago by semenov

Just in case, the expected query is:

SELECT `tracker_car`.`id`, `tracker_car`.`content_type_id`, `tracker_car`.`object_id`, `tracker_truck`.`car_ptr_id`
FROM `tracker_truck`
INNER JOIN `tracker_car` ON (`tracker_truck`.`car_ptr_id` = `tracker_car`.`id`)
WHERE `tracker_car`.`object_id` = 1
  • the redundant JOIN to itself removed along with its alias, and there's no "LIMIT 21".

I will probably look into the related ORM code on the weekend.

comment:6 Changed 4 years ago by carljm

The magic "LIMIT 21" is added because the QuerySet is evaluated via repr. This is a safety feature to prevent careless use of " shell" from bringing your database to its knees.

comment:7 Changed 3 years ago by lukeplant

  • Type set to Bug

comment:8 Changed 3 years ago by lukeplant

  • Severity set to Normal

comment:9 Changed 3 years ago by anonymous

  • Component changed from Database layer (models, ORM) to contrib.contenttypes

comment:10 Changed 2 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:11 Changed 2 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:12 Changed 18 months ago by ramiro

See also #13203.

Add Comment

Modify Ticket

Change Properties
<Author field>
as new
The owner will be changed from nobody to anonymous. Next status will be 'assigned'
as The resolution will be set. Next status will be 'closed'

E-mail address and user name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.