diff --git a/mongoengine/fields.py b/mongoengine/fields.py index e9a5e4b2..9062333e 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -944,7 +944,7 @@ def key_has_dot_or_dollar(d): dictionary contains a dot or a dollar sign. """ for k, v in d.items(): - if ('.' in k or '$' in k) or (isinstance(v, dict) and key_has_dot_or_dollar(v)): + if ('.' in k or k.startswith('$')) or (isinstance(v, dict) and key_has_dot_or_dollar(v)): return True @@ -977,7 +977,7 @@ class DictField(ComplexBaseField): self.error(msg) if key_has_dot_or_dollar(value): self.error('Invalid dictionary key name - keys may not contain "."' - ' or "$" characters') + ' or startswith "$" characters') super(DictField, self).validate(value) def lookup_member(self, member_name): diff --git a/tests/fields/fields.py b/tests/fields/fields.py index 0f325849..b09c0a2d 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -1698,6 +1698,10 @@ class FieldTest(MongoDBTestCase): post.info = {'title': 'test'} post.save() + post = BlogPost() + post.info = {'title' : 'dollar_sign', 'details' : {'te$t' : 'test'} } + post.save() + post = BlogPost() post.info = {'details': {'test': 'test'}} post.save() @@ -1706,12 +1710,15 @@ class FieldTest(MongoDBTestCase): post.info = {'details': {'test': 3}} post.save() - self.assertEqual(BlogPost.objects.count(), 3) + self.assertEqual(BlogPost.objects.count(), 4) self.assertEqual( BlogPost.objects.filter(info__title__exact='test').count(), 1) self.assertEqual( BlogPost.objects.filter(info__details__test__exact='test').count(), 1) + post = BlogPost.objects.filter(info__title__exact='dollar_sign').first() + self.assertIn('te$t', post['info']['details']) + # Confirm handles non strings or non existing keys self.assertEqual( BlogPost.objects.filter(info__details__test__exact=5).count(), 0)