Fix querying an embedded document field by an invalid value (#1440)
This commit is contained in:
		
				
					committed by
					
						
						Stefan Wójcik
					
				
			
			
				
	
			
			
			
						parent
						
							96d20756ca
						
					
				
				
					commit
					9f4b04ea0f
				
			@@ -16,8 +16,7 @@ from mongoengine.base.datastructures import (BaseDict, BaseList,
 | 
			
		||||
                                             SemiStrictDict, StrictDict)
 | 
			
		||||
from mongoengine.base.fields import ComplexBaseField
 | 
			
		||||
from mongoengine.common import _import_class
 | 
			
		||||
from mongoengine.errors import (FieldDoesNotExist, InvalidDocumentError,
 | 
			
		||||
                                LookUpError, OperationError, ValidationError)
 | 
			
		||||
from mongoengine.errors import (FieldDoesNotExist, InvalidDocumentError, LookUpError, OperationError, ValidationError)
 | 
			
		||||
 | 
			
		||||
__all__ = ('BaseDocument',)
 | 
			
		||||
 | 
			
		||||
@@ -675,6 +674,9 @@ class BaseDocument(object):
 | 
			
		||||
        if not only_fields:
 | 
			
		||||
            only_fields = []
 | 
			
		||||
 | 
			
		||||
        if son and not isinstance(son, dict):
 | 
			
		||||
            raise ValueError("The source SON object needs to be of type 'dict'")
 | 
			
		||||
 | 
			
		||||
        # Get the class name from the document, falling back to the given
 | 
			
		||||
        # class if unavailable
 | 
			
		||||
        class_name = son.get('_cls', cls._class_name)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ from mongoengine.base import (BaseDocument, BaseField, ComplexBaseField,
 | 
			
		||||
                              GeoJsonBaseField, ObjectIdField, get_document)
 | 
			
		||||
from mongoengine.connection import DEFAULT_CONNECTION_NAME, get_db
 | 
			
		||||
from mongoengine.document import Document, EmbeddedDocument
 | 
			
		||||
from mongoengine.errors import DoesNotExist, ValidationError
 | 
			
		||||
from mongoengine.errors import DoesNotExist, InvalidQueryError, ValidationError
 | 
			
		||||
from mongoengine.python_support import StringIO
 | 
			
		||||
from mongoengine.queryset import DO_NOTHING, QuerySet
 | 
			
		||||
 | 
			
		||||
@@ -566,7 +566,11 @@ class EmbeddedDocumentField(BaseField):
 | 
			
		||||
 | 
			
		||||
    def prepare_query_value(self, op, value):
 | 
			
		||||
        if value is not None and not isinstance(value, self.document_type):
 | 
			
		||||
            try:
 | 
			
		||||
                value = self.document_type._from_son(value)
 | 
			
		||||
            except ValueError:
 | 
			
		||||
                raise InvalidQueryError("Querying the embedded document '%s' failed, due to an invalid query value" %
 | 
			
		||||
                                        (self.document_type._class_name,))
 | 
			
		||||
        super(EmbeddedDocumentField, self).prepare_query_value(op, value)
 | 
			
		||||
        return self.to_mongo(value)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1860,6 +1860,10 @@ class InstanceTest(unittest.TestCase):
 | 
			
		||||
                'occurs': {"hello": None}
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        # Tests for issue #1438: https://github.com/MongoEngine/mongoengine/issues/1438
 | 
			
		||||
        with self.assertRaises(ValueError):
 | 
			
		||||
            Word._from_son('this is not a valid SON dict')
 | 
			
		||||
 | 
			
		||||
    def test_reverse_delete_rule_cascade_and_nullify(self):
 | 
			
		||||
        """Ensure that a referenced document is also deleted upon deletion.
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -1266,7 +1266,7 @@ class QuerySetTest(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_find_embedded(self):
 | 
			
		||||
        """Ensure that an embedded document is properly returned from
 | 
			
		||||
        a query.
 | 
			
		||||
        different manners of querying.
 | 
			
		||||
        """
 | 
			
		||||
        class User(EmbeddedDocument):
 | 
			
		||||
            name = StringField()
 | 
			
		||||
@@ -1277,8 +1277,9 @@ class QuerySetTest(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
        BlogPost.drop_collection()
 | 
			
		||||
 | 
			
		||||
        user = User(name='Test User')
 | 
			
		||||
        BlogPost.objects.create(
 | 
			
		||||
            author=User(name='Test User'),
 | 
			
		||||
            author=user,
 | 
			
		||||
            content='Had a good coffee today...'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
@@ -1286,6 +1287,19 @@ class QuerySetTest(unittest.TestCase):
 | 
			
		||||
        self.assertTrue(isinstance(result.author, User))
 | 
			
		||||
        self.assertEqual(result.author.name, 'Test User')
 | 
			
		||||
 | 
			
		||||
        result = BlogPost.objects.get(author__name=user.name)
 | 
			
		||||
        self.assertTrue(isinstance(result.author, User))
 | 
			
		||||
        self.assertEqual(result.author.name, 'Test User')
 | 
			
		||||
 | 
			
		||||
        result = BlogPost.objects.get(author={'name': user.name})
 | 
			
		||||
        self.assertTrue(isinstance(result.author, User))
 | 
			
		||||
        self.assertEqual(result.author.name, 'Test User')
 | 
			
		||||
 | 
			
		||||
        # Fails, since the string is not a type that is able to represent the
 | 
			
		||||
        # author's document structure (should be dict)
 | 
			
		||||
        with self.assertRaises(InvalidQueryError):
 | 
			
		||||
            BlogPost.objects.get(author=user.name)
 | 
			
		||||
 | 
			
		||||
    def test_find_empty_embedded(self):
 | 
			
		||||
        """Ensure that you can save and find an empty embedded document."""
 | 
			
		||||
        class User(EmbeddedDocument):
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user