From 7f892cedbad13b444151a1c163a328d968ee6b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anssi=20K=C3=A4=C3=A4ri=C3=A4inen?= Date: Fri, 26 Jul 2013 13:02:32 +0300 Subject: [PATCH] [1.6.x] Fixed related model lookup regression It has been possible to use models of wrong type in related field lookups. For example pigs__in=[a_duck] has worked. Changes to ForeignObject broke that. It might be a good idea to restrict the model types usable in lookups. This should be done intentionally, not accidentally and without any consideration for deprecation path. Backpatch of 7cca8d56d28e321ffc395c92f82d97adaa0dcf94 from master. --- django/db/models/fields/related.py | 2 +- tests/queries/tests.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index b288a822982..5c13205fbbe 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -1060,7 +1060,7 @@ class ForeignObject(RelatedField): value_list = [] for source in sources: # Account for one-to-one relations when sent a different model - while not isinstance(value, source.model): + while not isinstance(value, source.model) and source.rel: source = source.rel.to._meta.get_field(source.rel.field_name) value_list.append(getattr(value, source.attname)) return tuple(value_list) diff --git a/tests/queries/tests.py b/tests/queries/tests.py index 352e87a6345..ff6c0bb7a1d 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -2927,3 +2927,19 @@ class Ticket18785Tests(unittest.TestCase): ).order_by() self.assertEqual(1, str(qs.query).count('INNER JOIN')) self.assertEqual(0, str(qs.query).count('OUTER JOIN')) + +class RelatedLookupTypeTests(TestCase): + def test_wrong_type_lookup(self): + oa = ObjectA.objects.create(name="oa") + wrong_type = Order.objects.create(id=oa.pk) + ob = ObjectB.objects.create(name="ob", objecta=oa, num=1) + # Currently Django doesn't care if the object is of correct + # type, it will just use the objecta's related fields attribute + # (id) for model lookup. Making things more restrictive could + # be a good idea... + self.assertQuerysetEqual( + ObjectB.objects.filter(objecta=wrong_type), + [ob], lambda x: x) + self.assertQuerysetEqual( + ObjectB.objects.filter(objecta__in=[wrong_type]), + [ob], lambda x: x)