diff --git a/.gitignore b/.gitignore index 42dcc6e..57cf1b7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ docs/.build docs/_build build/ dist/ -mongoengine.egg-info/ \ No newline at end of file +mongoengine.egg-info/ +env/ \ No newline at end of file diff --git a/mongoengine/base.py b/mongoengine/base.py index 9f54cd7..4523a26 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -410,8 +410,6 @@ class BaseDocument(object): value = getattr(self, field_name, None) if value is not None: data[field.db_field] = field.to_mongo(value) - else: - data[field.db_field] = None # Only add _cls and _types if allow_inheritance is not False if not (hasattr(self, '_meta') and self._meta.get('allow_inheritance', True) == False): @@ -454,7 +452,8 @@ class BaseDocument(object): for field_name, field in cls._fields.items(): if field.db_field in data: value = data[field.db_field] - data[field_name] = value if value is None else field.to_python(value) + data[field_name] = (value if value is None + else field.to_python(value)) obj = cls(**data) obj._present_fields = present_fields diff --git a/mongoengine/fields.py b/mongoengine/fields.py index d8d310d..dc5dbe0 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -66,6 +66,9 @@ class StringField(BaseField): regex = r'%s$' elif op == 'exact': regex = r'^%s$' + + # escape unsafe characters which could lead to a re.error + value = re.escape(value) value = re.compile(regex % value, flags) return value diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index 00a7f7a..0b9218a 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -135,7 +135,6 @@ class Q(object): # Handle DBRef if isinstance(value, pymongo.dbref.DBRef): - # this.created_user.$id == "4c4c56f8cc1831418c000000" op_js = '(this.%(field)s.$id == "%(id)s" &&'\ ' this.%(field)s.$ref == "%(ref)s")' % { 'field': key, @@ -239,6 +238,10 @@ class QuerySet(object): """An alias of :meth:`~mongoengine.queryset.QuerySet.__call__` """ return self.__call__(*q_objs, **query) + + def all(self): + """Returns all documents.""" + return self.__call__() @property def _collection(self): @@ -667,11 +670,13 @@ class QuerySet(object): """ key_list = [] for key in keys: + if not key: continue direction = pymongo.ASCENDING if key[0] == '-': direction = pymongo.DESCENDING if key[0] in ('-', '+'): key = key[1:] + key = key.replace('__', '.') key_list.append((key, direction)) self._ordering = key_list diff --git a/tests/fields.py b/tests/fields.py index ef776d4..1e53d23 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -674,7 +674,12 @@ class FieldTest(unittest.TestCase): PutFile.drop_collection() StreamFile.drop_collection() SetFile.drop_collection() - + + # Make sure FileField is optional and not required + class DemoFile(Document): + file = FileField() + d = DemoFile.objects.create() + def test_geo_indexes(self): """Ensure that indexes are created automatically for GeoPointFields. """ @@ -694,7 +699,7 @@ class FieldTest(unittest.TestCase): Event.drop_collection() def test_ensure_unique_default_instances(self): - """Ensure that every document has it's own unique default instance.""" + """Ensure that every field has it's own unique default instance.""" class D(Document): data = DictField() data2 = DictField(default=lambda: {}) diff --git a/tests/queryset.py b/tests/queryset.py index b1f1657..b339d61 100644 --- a/tests/queryset.py +++ b/tests/queryset.py @@ -288,6 +288,13 @@ class QuerySetTest(unittest.TestCase): self.assertEqual(obj, person) obj = self.Person.objects(Q(name__iexact='gUIDO VAN rOSSU')).first() self.assertEqual(obj, None) + + # Test unsafe expressions + person = self.Person(name='Guido van Rossum [.\'Geek\']') + person.save() + + obj = self.Person.objects(Q(name__icontains='[.\'Geek')).first() + self.assertEqual(obj, person) def test_filter_chaining(self): """Ensure filters can be chained together.