Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#18432 closed Bug (fixed)

Chained foreign keys with to_field produce incorrect query

Reported by: lwarx Owned by: Spark23
Component: Database layer (models, ORM) Version: 1.3
Severity: Normal Keywords:
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

Example models:

class Model1(models.Model):
    pkey = models.IntegerField(unique=True, db_index=True)

class Model2(models.Model):
    model1 = models.ForeignKey(Model1, unique=True, to_field='pkey')

class Model3(models.Model):
    model2 = models.ForeignKey(Model2, unique=True, to_field='model1')

Steps to reproduce:

m1 = Model1(pkey=1000); m1.save(); m2 = Model2(model1=m1); m2.save(); m3 = Model3(model2=m2); m3.save()
(0.000) INSERT INTO `testcase_model1` (`pkey`) VALUES (1000); args=(1000,)
(0.000) INSERT INTO `testcase_model2` (`model1_id`) VALUES (1000); args=(1000,)
(0.000) INSERT INTO `testcase_model3` (`model2_id`) VALUES (1000); args=(1000,)

m3 = Model3.objects.get(model2=1000)
(0.001) SELECT `testcase_model3`.`id`, `testcase_model3`.`model2_id` FROM `testcase_model3` WHERE `testcase_model3`.`model2_id` = 1000 ; args=(1000,)

m3.model2
(0.000) SELECT `testcase_model2`.`id`, `testcase_model2`.`model1_id` FROM `testcase_model2` INNER JOIN `testcase_model1` ON (`testcase_model2`.`model1_id` = `testcase_model1`.`pkey`) WHERE `testcase_model1`.`id` = 1000 ; args=(1000,)

In the last query WHERE condition is incorrect - it does not respect to_field attribute and uses primary key instead.

Error message:

DoesNotExist                              Traceback (most recent call last)
/private/tmp/fkchain/<ipython-input-5-2fce98c5af10> in <module>()
----> 1 m3.model2

/Library/Python/2.7/site-packages/django/db/models/fields/related.pyc in __get__(self, instance, instance_type)
    313                 rel_obj = rel_mgr.using(db).get(**params)
    314             else:
--> 315                 rel_obj = QuerySet(self.field.rel.to).using(db).get(**params)
    316             setattr(instance, cache_name, rel_obj)
    317             return rel_obj

/Library/Python/2.7/site-packages/django/db/models/query.pyc in get(self, *args, **kwargs)
    347         if not num:
    348             raise self.model.DoesNotExist("%s matching query does not exist."
--> 349                     % self.model._meta.object_name)
    350         raise self.model.MultipleObjectsReturned("get() returned more than one %s -- it returned %s! Lookup parameters were %s"
    351                 % (self.model._meta.object_name, num, kwargs))

DoesNotExist: Model2 matching query does not exist.

Change History (5)

comment:1 Changed 3 years ago by Spark23

  • Needs documentation unset
  • Needs tests unset
  • Owner changed from nobody to Spark23
  • Patch needs improvement unset
  • Status changed from new to assigned

comment:2 Changed 3 years ago by Spark23

  • Has patch set
  • Resolution set to fixed
  • Status changed from assigned to closed
  • Triage Stage changed from Unreviewed to Ready for checkin

fixed in pull request #126 on github

comment:3 Changed 3 years ago by jezdez

  • Resolution fixed deleted
  • Status changed from closed to reopened

comment:4 Changed 3 years ago by Jannis Leidel <jannis@…>

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

In [1a412dda621d8623abb91f8687f52de30a79901a]:

Fixed #18432 -- Prevented the ForeignKey field from creating an invalid query when chained. Thanks, Jann Kleen.

comment:5 Changed 3 years ago by lwarx

Thanks a lot!

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