added OrderedDocument class to decode BSON data to OrderedDict for retrieving data in order

This commit is contained in:
Hiroyasu OHYAMA 2017-02-28 03:35:39 +00:00
parent 6810953014
commit 84a8f1eb2b
2 changed files with 31 additions and 1 deletions

View File

@ -1,6 +1,7 @@
import re
import warnings
from collections import OrderedDict
from bson.dbref import DBRef
import pymongo
from pymongo.read_preferences import ReadPreference
@ -21,7 +22,8 @@ from mongoengine.queryset import (NotUniqueError, OperationError,
__all__ = ('Document', 'EmbeddedDocument', 'DynamicDocument',
'DynamicEmbeddedDocument', 'OperationError',
'InvalidCollectionError', 'NotUniqueError', 'MapReduceDocument')
'InvalidCollectionError', 'NotUniqueError', 'MapReduceDocument',
'OrderedDocument')
def includes_cls(fields):
@ -1036,3 +1038,27 @@ 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

@ -1501,6 +1501,10 @@ 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+