Merge branch 'master' into 0.7

This commit is contained in:
Ross Lawley
2012-09-03 15:20:17 +01:00
9 changed files with 149 additions and 33 deletions

View File

@@ -11,7 +11,7 @@ from queryset import DoesNotExist, MultipleObjectsReturned
from queryset import DO_NOTHING
from mongoengine import signals
from mongoengine.python_support import (PY3, PY25, txt_type,
from mongoengine.python_support import (PY3, UNICODE_KWARGS, txt_type,
to_str_keys_recursive)
import pymongo
@@ -949,8 +949,10 @@ class BaseDocument(object):
self._data[name] = value
if hasattr(self, '_changed_fields'):
self._mark_as_changed(name)
if (self._is_document and not self._created and
name in self._meta.get('shard_key', tuple())):
name in self._meta.get('shard_key', tuple()) and
self._data.get(name) != value):
OperationError = _import_class('OperationError')
msg = "Shard Keys are immutable. Tried to update %s" % name
raise OperationError(msg)
@@ -1052,9 +1054,9 @@ class BaseDocument(object):
# class if unavailable
class_name = son.get('_cls', cls._class_name)
data = dict(("%s" % key, value) for key, value in son.items())
if PY25:
# PY25 cannot handle unicode keys passed to class constructor
# example: cls(**data)
if not UNICODE_KWARGS:
# python 2.6.4 and lower cannot handle unicode keys
# passed to class constructor example: cls(**data)
to_str_keys_recursive(data)
if '_types' in data:

View File

@@ -295,6 +295,16 @@ class Document(BaseDocument):
ref.save(**kwargs)
ref._changed_fields = []
@property
def _object_key(self):
"""Dict to identify object in collection
"""
select_dict = {'pk': self.pk}
shard_key = self.__class__._meta.get('shard_key', tuple())
for k in shard_key:
select_dict[k] = getattr(self, k)
return select_dict
def update(self, **kwargs):
"""Performs an update on the :class:`~mongoengine.Document`
A convenience wrapper to :meth:`~mongoengine.QuerySet.update`.
@@ -306,11 +316,7 @@ class Document(BaseDocument):
raise OperationError('attempt to update a document not yet saved')
# Need to add shard key to query, or you get an error
select_dict = {'pk': self.pk}
shard_key = self.__class__._meta.get('shard_key', tuple())
for k in shard_key:
select_dict[k] = getattr(self, k)
return self.__class__.objects(**select_dict).update_one(**kwargs)
return self.__class__.objects(**self._object_key).update_one(**kwargs)
def delete(self, safe=False):
"""Delete the :class:`~mongoengine.Document` from the database. This
@@ -321,7 +327,7 @@ class Document(BaseDocument):
signals.pre_delete.send(self.__class__, document=self)
try:
self.__class__.objects(pk=self.pk).delete(safe=safe)
self.__class__.objects(**self._object_key).delete(safe=safe)
except pymongo.errors.OperationFailure, err:
message = u'Could not delete document (%s)' % err.message
raise OperationError(message)

View File

@@ -4,6 +4,7 @@ import sys
PY3 = sys.version_info[0] == 3
PY25 = sys.version_info[:2] == (2, 5)
UNICODE_KWARGS = int(''.join([str(x) for x in sys.version_info[:3]])) > 264
if PY3:
import codecs

View File

@@ -218,7 +218,7 @@ class QNode(object):
def _combine(self, other, operation):
"""Combine this node with another node into a QCombination object.
"""
if other.empty:
if getattr(other, 'empty', True):
return self
if self.empty:
@@ -398,12 +398,12 @@ class QuerySet(object):
or a **-** to determine the index ordering
"""
index_spec = QuerySet._build_index_spec(self._document, key_or_list)
self._collection.ensure_index(
index_spec['fields'],
drop_dups=drop_dups,
background=background,
sparse=index_spec.get('sparse', False),
unique=index_spec.get('unique', False))
fields = index_spec.pop('fields')
index_spec['drop_dups'] = drop_dups
index_spec['background'] = background
index_spec.update(kwargs)
self._collection.ensure_index(fields, **index_spec)
return self
def __call__(self, q_obj=None, class_check=True, slave_okay=False, **query):
@@ -473,11 +473,11 @@ class QuerySet(object):
# Ensure document-defined indexes are created
if self._document._meta['index_specs']:
for spec in self._document._meta['index_specs']:
types_indexed = types_indexed or includes_types(spec['fields'])
fields = spec.pop('fields')
types_indexed = types_indexed or includes_types(fields)
opts = index_opts.copy()
opts['unique'] = spec.get('unique', False)
opts['sparse'] = spec.get('sparse', False)
self._collection.ensure_index(spec['fields'],
opts.update(spec)
self._collection.ensure_index(fields,
background=background, **opts)
# If _types is being used (for polymorphism), it needs an index,
@@ -1343,6 +1343,12 @@ class QuerySet(object):
"""
doc = self._document
# Handle deletes where skips or limits have been applied
if self._skip or self._limit:
for doc in self:
doc.delete()
return
delete_rules = doc._meta.get('delete_rules') or {}
# Check for DENY rules before actually deleting/nullifying any other
# references