To achive storing object data in order with minimum implementation, I

changed followings.

- added optional parameter `container_class` which enables to choose
  intermediate class at encoding Python data, instead of additional
  field class.
- removed OrderedDocument class because the equivalent feature could
  be implemented by the outside of Mongoengine.
This commit is contained in:
Hiroyasu OHYAMA
2017-03-01 09:20:57 +00:00
parent e32a9777d7
commit 5957dc72eb
4 changed files with 29 additions and 70 deletions

View File

@@ -1,7 +1,6 @@
import re
import warnings
from collections import OrderedDict
from bson.dbref import DBRef
import pymongo
from pymongo.read_preferences import ReadPreference
@@ -22,8 +21,7 @@ from mongoengine.queryset import (NotUniqueError, OperationError,
__all__ = ('Document', 'EmbeddedDocument', 'DynamicDocument',
'DynamicEmbeddedDocument', 'OperationError',
'InvalidCollectionError', 'NotUniqueError', 'MapReduceDocument',
'OrderedDocument')
'InvalidCollectionError', 'NotUniqueError', 'MapReduceDocument')
def includes_cls(fields):
@@ -1038,27 +1036,3 @@ class MapReduceDocument(object):
self._key_object = self._document.objects.with_id(self.key)
return self._key_object
return self._key_object
class OrderedDocument(Document):
"""A document that is almost same with Document except for returning
results in OrderedDict instead of dict.
"""
# The __metaclass__ attribute is removed by 2to3 when running with Python3
# my_metaclass is defined so that metaclass can be queried in Python 2 & 3
my_metaclass = TopLevelDocumentMetaclass
__metaclass__ = TopLevelDocumentMetaclass
@classmethod
def _get_collection(cls):
collection = super(OrderedDocument, cls)._get_collection()
if IS_PYMONGO_3:
# returns collection object which is set OrderedDict class to be decoded from BSON document
from bson import CodecOptions
return collection.with_options(codec_options=CodecOptions(document_class=OrderedDict))
else:
# set attribute to specify the class to be decoeded
cls.decoded_class = OrderedDict
return collection

View File

@@ -5,7 +5,6 @@ import re
import time
import uuid
import warnings
from collections import OrderedDict
from operator import itemgetter
from bson import Binary, DBRef, ObjectId, SON
@@ -50,7 +49,7 @@ __all__ = (
'FileField', 'ImageGridFsProxy', 'ImproperlyConfigured', 'ImageField',
'GeoPointField', 'PointField', 'LineStringField', 'PolygonField',
'SequenceField', 'UUIDField', 'MultiPointField', 'MultiLineStringField',
'MultiPolygonField', 'GeoJsonBaseField', 'OrderedDynamicField'
'MultiPolygonField', 'GeoJsonBaseField'
)
RECURSIVE_REFERENCE_CONSTANT = 'self'
@@ -620,6 +619,14 @@ class DynamicField(BaseField):
Used by :class:`~mongoengine.DynamicDocument` to handle dynamic data"""
def __init__(self, container_class=dict, *args, **kwargs):
self._container_cls = container_class
if not issubclass(self._container_cls, dict):
self.error('The class that is specified in `container_class` parameter '
'must be a subclass of `dict`.')
super(DynamicField, self).__init__(*args, **kwargs)
def to_mongo(self, value, use_db_field=True, fields=None):
"""Convert a Python type to a MongoDB compatible type.
"""
@@ -645,7 +652,7 @@ class DynamicField(BaseField):
is_list = True
value = {k: v for k, v in enumerate(value)}
data = self._container_type() if hasattr(self, '_container_type') else {}
data = self._container_cls()
for k, v in value.iteritems():
data[k] = self.to_mongo(v, use_db_field, fields)
@@ -676,16 +683,6 @@ class DynamicField(BaseField):
value.validate(clean=clean)
class OrderedDynamicField(DynamicField):
"""A field that wraps DynamicField. This uses OrderedDict class
to guarantee to store data in the defined order instead of dict.
"""
def __init__(self, *args, **kwargs):
super(OrderedDynamicField, self).__init__(*args, **kwargs)
self._container_type = OrderedDict
class ListField(ComplexBaseField):
"""A list field that wraps a standard field, allowing multiple instances
of the field to be used as a list in the database.

View File

@@ -1501,10 +1501,6 @@ class BaseQuerySet(object):
cursor_args['read_preference'] = self._read_preference
else:
cursor_args['slave_okay'] = self._slave_okay
# set decode format if needed
if hasattr(self._document, 'decoded_class'):
cursor_args['as_class'] = self._document.decoded_class
else:
fields_name = 'projection'
# snapshot is not handled at all by PyMongo 3+