Opened 15 years ago
Closed 9 years ago
#12885 closed Bug (fixed)
GenericRelation fails to join the related table from a inherited model
Reported by: | Ilya Semenov | Owned by: | nobody |
---|---|---|---|
Component: | contrib.contenttypes | Version: | 1.1 |
Severity: | Normal | Keywords: | |
Cc: | Carl Meyer | 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
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): pass 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 (1)
Change History (17)
comment:1 by , 15 years ago
Cc: | added |
---|
comment:2 by , 15 years ago
Component: | ORM aggregation → Database layer (models, ORM) |
---|---|
Owner: | set to |
comment:3 by , 15 years ago
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 by , 15 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:5 by , 15 years ago
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 by , 15 years ago
The magic "LIMIT 21" is added because the QuerySet is evaluated via repr. This is a safety feature to prevent careless use of "manage.py shell" from bringing your database to its knees.
comment:7 by , 14 years ago
Type: | → Bug |
---|
comment:8 by , 14 years ago
Severity: | → Normal |
---|
comment:9 by , 14 years ago
Component: | Database layer (models, ORM) → contrib.contenttypes |
---|
comment:13 by , 9 years ago
This remains an issue as of 58c7ff39fb265754fb17ab8d7f8a1401b355777b (Django 1.10 dev).
Here's the query for the attached failing test:
SELECT "generic_relations_mineral"."id", "generic_relations_mineral"."name", "generic_relations_mineral"."hardness", "generic_relations_valuablerock"."mineral_ptr_id" FROM "generic_relations_valuablerock" INNER JOIN "generic_relations_valuabletaggeditem" ON ("generic_relations_valuablerock"."mineral_ptr_id" = "generic_relations_valuabletaggeditem"."object_id" AND ("generic_relations_valuabletaggeditem"."content_type_id" = 13)) INNER JOIN "generic_relations_taggeditem" ON ("generic_relations_valuabletaggeditem"."taggeditem_ptr_id" = "generic_relations_taggeditem"."id") INNER JOIN "generic_relations_mineral" ON ("generic_relations_valuablerock"."mineral_ptr_id" = "generic_relations_mineral"."id") WHERE "generic_relations_taggeditem"."tag" = countertop
Traceback:
File "/home/tim/code/django/django/db/backends/sqlite3/base.py", line 323, in execute return Database.Cursor.execute(self, query, params) django.db.utils.OperationalError: no such column: generic_relations_valuabletaggeditem.object_id
by , 9 years ago
Attachment: | 12885-test.diff added |
---|
comment:14 by , 9 years ago
Has patch: | set |
---|
I've created a PR for this (see https://github.com/django/django/pull/5487). Luckily the changes needed here were only to contrib.contenttypes. This is always a good sign, we likely don't have a more fundamental problem. Lets see what CI things of my PR...
comment:15 by , 9 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Can you exercise the same test case you've created against SVN trunk and report back the results please?