From c5f23ad93d669420112f8979f4d939a577eaaaf8 Mon Sep 17 00:00:00 2001 From: DavidBord Date: Thu, 18 Sep 2014 10:35:35 +0300 Subject: [PATCH] fix-#744: Querying by a field defined in a subclass raises InvalidQueryError --- docs/changelog.rst | 1 + mongoengine/base/document.py | 13 +++++++++++++ tests/queryset/queryset.py | 17 +++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 6925bc30..1feec343 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Changelog Changes in 0.9.X - DEV ====================== +- Querying by a field defined in a subclass raises InvalidQueryError #744 - Add Support For MongoDB 2.6.X's maxTimeMS #778 - abstract shouldn't be inherited in EmbeddedDocument # 789 - Allow specifying the '_cls' as a field for indexes #397 diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index 869449f9..05fd1faf 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -884,6 +884,19 @@ class BaseDocument(object): elif cls._dynamic: DynamicField = _import_class('DynamicField') field = DynamicField(db_field=field_name) + elif cls._meta.get("allow_inheritance", False) or cls._meta.get("abstract", False): + # 744: in case the field is defined in a subclass + field = None + for subcls in cls.__subclasses__(): + try: + field = subcls._lookup_field([field_name])[0] + except LookUpError: + continue + + if field is not None: + break + else: + raise LookUpError('Cannot resolve field "%s"' % field_name) else: raise LookUpError('Cannot resolve field "%s"' % field_name) diff --git a/tests/queryset/queryset.py b/tests/queryset/queryset.py index 8efee8b3..7f548999 100644 --- a/tests/queryset/queryset.py +++ b/tests/queryset/queryset.py @@ -4405,6 +4405,23 @@ class QuerySetTest(unittest.TestCase): # 778: max_time_ms can get only int or None as input self.assertRaises(TypeError, self.Person.objects(name="name").max_time_ms, "not a number") + def test_subclass_field_query(self): + class Animal(Document): + is_mamal = BooleanField() + meta = dict(allow_inheritance=True) + + class Cat(Animal): + whiskers_length = FloatField() + + class ScottishCat(Cat): + folded_ears = BooleanField() + + Animal(is_mamal=False).save() + Cat(is_mamal=True, whiskers_length=5.1).save() + ScottishCat(is_mamal=True, folded_ears=True).save() + self.assertEquals(Animal.objects(folded_ears=True).count(), 1) + self.assertEquals(Animal.objects(whiskers_length=5.1).count(), 1) + if __name__ == '__main__': unittest.main()