Merge remote branch 'hmarr/master'
Conflicts: mongoengine/fields.py
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
from queryset import QuerySet, QuerySetManager
|
||||
from queryset import DoesNotExist, MultipleObjectsReturned
|
||||
|
||||
import sys
|
||||
import pymongo
|
||||
|
||||
|
||||
@@ -167,7 +169,22 @@ class DocumentMetaclass(type):
|
||||
for field in new_class._fields.values():
|
||||
field.owner_document = new_class
|
||||
|
||||
module = attrs.pop('__module__')
|
||||
|
||||
new_class.add_to_class('DoesNotExist', subclass_exception('DoesNotExist',
|
||||
tuple(x.DoesNotExist
|
||||
for k,x in superclasses.items())
|
||||
or (DoesNotExist,), module))
|
||||
|
||||
new_class.add_to_class('MultipleObjectsReturned', subclass_exception('MultipleObjectsReturned',
|
||||
tuple(x.MultipleObjectsReturned
|
||||
for k,x in superclasses.items())
|
||||
or (MultipleObjectsReturned,), module))
|
||||
return new_class
|
||||
|
||||
|
||||
def add_to_class(self, name, value):
|
||||
setattr(self, name, value)
|
||||
|
||||
|
||||
class TopLevelDocumentMetaclass(DocumentMetaclass):
|
||||
@@ -417,3 +434,11 @@ class BaseDocument(object):
|
||||
if self.id == other.id:
|
||||
return True
|
||||
return False
|
||||
|
||||
if sys.version_info < (2, 5):
|
||||
# Prior to Python 2.5, Exception was an old-style class
|
||||
def subclass_exception(name, parents, unused):
|
||||
return types.ClassType(name, parents, {})
|
||||
else:
|
||||
def subclass_exception(name, parents, module):
|
||||
return type(name, parents, {'__module__': module})
|
||||
@@ -1,6 +1,7 @@
|
||||
from base import BaseField, ObjectIdField, ValidationError, get_document
|
||||
from document import Document, EmbeddedDocument
|
||||
from connection import _get_db
|
||||
from operator import itemgetter
|
||||
|
||||
import re
|
||||
import pymongo
|
||||
@@ -12,7 +13,7 @@ __all__ = ['StringField', 'IntField', 'FloatField', 'BooleanField',
|
||||
'DateTimeField', 'EmbeddedDocumentField', 'ListField', 'DictField',
|
||||
'ObjectIdField', 'ReferenceField', 'ValidationError',
|
||||
'DecimalField', 'URLField', 'GenericReferenceField',
|
||||
'BinaryField', 'EmailField', 'GeoLocationField']
|
||||
'BinaryField', 'SortedListField', 'EmailField', 'GeoLocationField']
|
||||
|
||||
RECURSIVE_REFERENCE_CONSTANT = 'self'
|
||||
|
||||
@@ -168,6 +169,9 @@ class DecimalField(BaseField):
|
||||
if not isinstance(value, basestring):
|
||||
value = unicode(value)
|
||||
return decimal.Decimal(value)
|
||||
|
||||
def to_mongo(self, value):
|
||||
return unicode(value)
|
||||
|
||||
def validate(self, value):
|
||||
if not isinstance(value, decimal.Decimal):
|
||||
@@ -320,6 +324,23 @@ class ListField(BaseField):
|
||||
def lookup_member(self, member_name):
|
||||
return self.field.lookup_member(member_name)
|
||||
|
||||
class SortedListField(ListField):
|
||||
"""A ListField that sorts the contents of its list before writing to
|
||||
the database in order to ensure that a sorted list is always
|
||||
retrieved.
|
||||
"""
|
||||
|
||||
_ordering = None
|
||||
|
||||
def __init__(self, field, **kwargs):
|
||||
if 'ordering' in kwargs.keys():
|
||||
self._ordering = kwargs.pop('ordering')
|
||||
super(SortedListField, self).__init__(field, **kwargs)
|
||||
|
||||
def to_mongo(self, value):
|
||||
if self._ordering is not None:
|
||||
return sorted([self.field.to_mongo(item) for item in value], key=itemgetter(self._ordering))
|
||||
return sorted([self.field.to_mongo(item) for item in value])
|
||||
|
||||
class DictField(BaseField):
|
||||
"""A dictionary field that wraps a standard Python dictionary. This is
|
||||
|
||||
@@ -14,7 +14,6 @@ REPR_OUTPUT_SIZE = 20
|
||||
class DoesNotExist(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class MultipleObjectsReturned(Exception):
|
||||
pass
|
||||
|
||||
@@ -26,6 +25,8 @@ class InvalidQueryError(Exception):
|
||||
class OperationError(Exception):
|
||||
pass
|
||||
|
||||
class InvalidCollectionError(Exception):
|
||||
pass
|
||||
|
||||
RE_TYPE = type(re.compile(''))
|
||||
|
||||
@@ -345,8 +346,9 @@ class QuerySet(object):
|
||||
def get(self, *q_objs, **query):
|
||||
"""Retrieve the the matching object raising
|
||||
:class:`~mongoengine.queryset.MultipleObjectsReturned` or
|
||||
:class:`~mongoengine.queryset.DoesNotExist` exceptions if multiple or
|
||||
no results are found.
|
||||
`DocumentName.MultipleObjectsReturned` exception if multiple results and
|
||||
:class:`~mongoengine.queryset.DoesNotExist` or `DocumentName.DoesNotExist`
|
||||
if no results are found.
|
||||
|
||||
.. versionadded:: 0.3
|
||||
"""
|
||||
@@ -356,16 +358,20 @@ class QuerySet(object):
|
||||
return self[0]
|
||||
elif count > 1:
|
||||
message = u'%d items returned, instead of 1' % count
|
||||
raise MultipleObjectsReturned(message)
|
||||
raise self._document.MultipleObjectsReturned(message)
|
||||
else:
|
||||
raise DoesNotExist('Document not found')
|
||||
raise self._document.DoesNotExist("%s matching query does not exist."
|
||||
% self._document._class_name)
|
||||
|
||||
def get_or_create(self, *q_objs, **query):
|
||||
"""Retreive unique object or create, if it doesn't exist. Raises
|
||||
:class:`~mongoengine.queryset.MultipleObjectsReturned` if multiple
|
||||
results are found. A new document will be created if the document
|
||||
doesn't exists; a dictionary of default values for the new document
|
||||
may be provided as a keyword argument called :attr:`defaults`.
|
||||
"""Retrieve unique object or create, if it doesn't exist. Returns a tuple of
|
||||
``(object, created)``, where ``object`` is the retrieved or created object
|
||||
and ``created`` is a boolean specifying whether a new object was created. Raises
|
||||
:class:`~mongoengine.queryset.MultipleObjectsReturned` or
|
||||
`DocumentName.MultipleObjectsReturned` if multiple results are found.
|
||||
A new document will be created if the document doesn't exists; a
|
||||
dictionary of default values for the new document may be provided as a
|
||||
keyword argument called :attr:`defaults`.
|
||||
|
||||
.. versionadded:: 0.3
|
||||
"""
|
||||
@@ -379,12 +385,12 @@ class QuerySet(object):
|
||||
query.update(defaults)
|
||||
doc = self._document(**query)
|
||||
doc.save()
|
||||
return doc
|
||||
return doc, True
|
||||
elif count == 1:
|
||||
return self.first()
|
||||
return self.first(), False
|
||||
else:
|
||||
message = u'%d items returned, instead of 1' % count
|
||||
raise MultipleObjectsReturned(message)
|
||||
raise self._document.MultipleObjectsReturned(message)
|
||||
|
||||
def first(self):
|
||||
"""Retrieve the first object matching the query.
|
||||
@@ -873,10 +879,6 @@ class QuerySet(object):
|
||||
return repr(data)
|
||||
|
||||
|
||||
class InvalidCollectionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class QuerySetManager(object):
|
||||
|
||||
def __init__(self, manager_func=None):
|
||||
|
||||
Reference in New Issue
Block a user