Updated docs, added force_insert to save()
This commit is contained in:
parent
ec927bdd63
commit
afd416c84e
@ -27,6 +27,8 @@ Querying
|
|||||||
.. autoclass:: mongoengine.queryset.QuerySet
|
.. autoclass:: mongoengine.queryset.QuerySet
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: mongoengine.queryset.QuerySet.__call__
|
||||||
|
|
||||||
.. autofunction:: mongoengine.queryset.queryset_manager
|
.. autofunction:: mongoengine.queryset.queryset_manager
|
||||||
|
|
||||||
Fields
|
Fields
|
||||||
|
@ -141,6 +141,7 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
|
|||||||
|
|
||||||
simple_class = True
|
simple_class = True
|
||||||
id_field = None
|
id_field = None
|
||||||
|
base_indexes = []
|
||||||
|
|
||||||
# Subclassed documents inherit collection from superclass
|
# Subclassed documents inherit collection from superclass
|
||||||
for base in bases:
|
for base in bases:
|
||||||
@ -156,6 +157,7 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
|
|||||||
collection = base._meta['collection']
|
collection = base._meta['collection']
|
||||||
|
|
||||||
id_field = id_field or base._meta.get('id_field')
|
id_field = id_field or base._meta.get('id_field')
|
||||||
|
base_indexes += base._meta.get('indexes', [])
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
'collection': collection,
|
'collection': collection,
|
||||||
@ -169,6 +171,8 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
|
|||||||
|
|
||||||
# Apply document-defined meta options
|
# Apply document-defined meta options
|
||||||
meta.update(attrs.get('meta', {}))
|
meta.update(attrs.get('meta', {}))
|
||||||
|
|
||||||
|
meta['indexes'] += base_indexes
|
||||||
|
|
||||||
# Only simple classes - direct subclasses of Document - may set
|
# Only simple classes - direct subclasses of Document - may set
|
||||||
# allow_inheritance to False
|
# allow_inheritance to False
|
||||||
|
@ -56,31 +56,51 @@ class Document(BaseDocument):
|
|||||||
|
|
||||||
__metaclass__ = TopLevelDocumentMetaclass
|
__metaclass__ = TopLevelDocumentMetaclass
|
||||||
|
|
||||||
def save(self, safe=True):
|
def save(self, safe=True, force_insert=False):
|
||||||
"""Save the :class:`~mongoengine.Document` to the database. If the
|
"""Save the :class:`~mongoengine.Document` to the database. If the
|
||||||
document already exists, it will be updated, otherwise it will be
|
document already exists, it will be updated, otherwise it will be
|
||||||
created.
|
created.
|
||||||
|
|
||||||
|
If ``safe=True`` and the operation is unsuccessful, an
|
||||||
|
:class:`~mongoengine.OperationError` will be raised.
|
||||||
|
|
||||||
|
:param safe: check if the operation succeeded before returning
|
||||||
|
:param force_insert: only try to create a new document, don't allow
|
||||||
|
updates of existing documents
|
||||||
"""
|
"""
|
||||||
self.validate()
|
self.validate()
|
||||||
doc = self.to_mongo()
|
doc = self.to_mongo()
|
||||||
try:
|
try:
|
||||||
object_id = self.__class__.objects._collection.save(doc, safe=safe)
|
collection = self.__class__.objects._collection
|
||||||
|
if force_insert:
|
||||||
|
object_id = collection.insert(doc, safe=safe)
|
||||||
|
else:
|
||||||
|
object_id = collection.save(doc, safe=safe)
|
||||||
except pymongo.errors.OperationFailure, err:
|
except pymongo.errors.OperationFailure, err:
|
||||||
raise OperationError('Tried to save duplicate unique keys (%s)'
|
message = 'Could not save document (%s)'
|
||||||
% str(err))
|
if 'duplicate key' in str(err):
|
||||||
|
message = 'Tried to save duplicate unique keys (%s)'
|
||||||
|
raise OperationError(message % str(err))
|
||||||
id_field = self._meta['id_field']
|
id_field = self._meta['id_field']
|
||||||
self[id_field] = self._fields[id_field].to_python(object_id)
|
self[id_field] = self._fields[id_field].to_python(object_id)
|
||||||
|
|
||||||
def delete(self):
|
def delete(self, safe=False):
|
||||||
"""Delete the :class:`~mongoengine.Document` from the database. This
|
"""Delete the :class:`~mongoengine.Document` from the database. This
|
||||||
will only take effect if the document has been previously saved.
|
will only take effect if the document has been previously saved.
|
||||||
|
|
||||||
|
:param safe: check if the operation succeeded before returning
|
||||||
"""
|
"""
|
||||||
id_field = self._meta['id_field']
|
id_field = self._meta['id_field']
|
||||||
object_id = self._fields[id_field].to_mongo(self[id_field])
|
object_id = self._fields[id_field].to_mongo(self[id_field])
|
||||||
self.__class__.objects(**{id_field: object_id}).delete()
|
try:
|
||||||
|
self.__class__.objects(**{id_field: object_id}).delete(safe=safe)
|
||||||
|
except pymongo.errors.OperationFailure, err:
|
||||||
|
raise OperationError('Could not delete document (%s)' % str(err))
|
||||||
|
|
||||||
def reload(self):
|
def reload(self):
|
||||||
"""Reloads all attributes from the database.
|
"""Reloads all attributes from the database.
|
||||||
|
|
||||||
|
.. versionadded:: 0.1.2
|
||||||
"""
|
"""
|
||||||
id_field = self._meta['id_field']
|
id_field = self._meta['id_field']
|
||||||
obj = self.__class__.objects(**{id_field: self[id_field]}).first()
|
obj = self.__class__.objects(**{id_field: self[id_field]}).first()
|
||||||
|
@ -82,6 +82,8 @@ class FloatField(BaseField):
|
|||||||
|
|
||||||
class BooleanField(BaseField):
|
class BooleanField(BaseField):
|
||||||
"""A boolean field type.
|
"""A boolean field type.
|
||||||
|
|
||||||
|
.. versionadded:: 0.1.2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
|
@ -121,6 +121,10 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def ensure_index(self, key_or_list):
|
def ensure_index(self, key_or_list):
|
||||||
"""Ensure that the given indexes are in place.
|
"""Ensure that the given indexes are in place.
|
||||||
|
|
||||||
|
:param key_or_list: a single index key or a list of index keys (to
|
||||||
|
construct a multi-field index); keys may be prefixed with a **+**
|
||||||
|
or a **-** to determine the index ordering
|
||||||
"""
|
"""
|
||||||
if isinstance(key_or_list, basestring):
|
if isinstance(key_or_list, basestring):
|
||||||
key_or_list = [key_or_list]
|
key_or_list = [key_or_list]
|
||||||
@ -146,6 +150,9 @@ class QuerySet(object):
|
|||||||
def __call__(self, *q_objs, **query):
|
def __call__(self, *q_objs, **query):
|
||||||
"""Filter the selected documents by calling the
|
"""Filter the selected documents by calling the
|
||||||
:class:`~mongoengine.QuerySet` with a query.
|
:class:`~mongoengine.QuerySet` with a query.
|
||||||
|
|
||||||
|
:param q_objs: :class:`~mongoengine.Q` objects to be used in the query
|
||||||
|
:param query: Django-style query keyword arguments
|
||||||
"""
|
"""
|
||||||
for q in q_objs:
|
for q in q_objs:
|
||||||
self._where_clauses.append(q.as_js(self._document))
|
self._where_clauses.append(q.as_js(self._document))
|
||||||
@ -269,6 +276,8 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def with_id(self, object_id):
|
def with_id(self, object_id):
|
||||||
"""Retrieve the object matching the id provided.
|
"""Retrieve the object matching the id provided.
|
||||||
|
|
||||||
|
:param object_id: the value for the id of the document to look up
|
||||||
"""
|
"""
|
||||||
id_field = self._document._meta['id_field']
|
id_field = self._document._meta['id_field']
|
||||||
object_id = self._document._fields[id_field].to_mongo(object_id)
|
object_id = self._document._fields[id_field].to_mongo(object_id)
|
||||||
@ -294,6 +303,8 @@ class QuerySet(object):
|
|||||||
def limit(self, n):
|
def limit(self, n):
|
||||||
"""Limit the number of returned documents to `n`. This may also be
|
"""Limit the number of returned documents to `n`. This may also be
|
||||||
achieved using array-slicing syntax (e.g. ``User.objects[:5]``).
|
achieved using array-slicing syntax (e.g. ``User.objects[:5]``).
|
||||||
|
|
||||||
|
:param n: the maximum number of objects to return
|
||||||
"""
|
"""
|
||||||
self._cursor.limit(n)
|
self._cursor.limit(n)
|
||||||
# Return self to allow chaining
|
# Return self to allow chaining
|
||||||
@ -302,6 +313,8 @@ class QuerySet(object):
|
|||||||
def skip(self, n):
|
def skip(self, n):
|
||||||
"""Skip `n` documents before returning the results. This may also be
|
"""Skip `n` documents before returning the results. This may also be
|
||||||
achieved using array-slicing syntax (e.g. ``User.objects[5:]``).
|
achieved using array-slicing syntax (e.g. ``User.objects[5:]``).
|
||||||
|
|
||||||
|
:param n: the number of objects to skip before returning results
|
||||||
"""
|
"""
|
||||||
self._cursor.skip(n)
|
self._cursor.skip(n)
|
||||||
return self
|
return self
|
||||||
@ -322,6 +335,9 @@ class QuerySet(object):
|
|||||||
"""Order the :class:`~mongoengine.queryset.QuerySet` by the keys. The
|
"""Order the :class:`~mongoengine.queryset.QuerySet` by the keys. The
|
||||||
order may be specified by prepending each of the keys by a + or a -.
|
order may be specified by prepending each of the keys by a + or a -.
|
||||||
Ascending order is assumed.
|
Ascending order is assumed.
|
||||||
|
|
||||||
|
:param keys: fields to order the query results by; keys may be
|
||||||
|
prefixed with **+** or **-** to determine the ordering direction
|
||||||
"""
|
"""
|
||||||
key_list = []
|
key_list = []
|
||||||
for key in keys:
|
for key in keys:
|
||||||
@ -338,6 +354,8 @@ class QuerySet(object):
|
|||||||
def explain(self, format=False):
|
def explain(self, format=False):
|
||||||
"""Return an explain plan record for the
|
"""Return an explain plan record for the
|
||||||
:class:`~mongoengine.queryset.QuerySet`\ 's cursor.
|
:class:`~mongoengine.queryset.QuerySet`\ 's cursor.
|
||||||
|
|
||||||
|
:param format: format the plan before returning it
|
||||||
"""
|
"""
|
||||||
|
|
||||||
plan = self._cursor.explain()
|
plan = self._cursor.explain()
|
||||||
@ -346,10 +364,12 @@ class QuerySet(object):
|
|||||||
plan = pprint.pformat(plan)
|
plan = pprint.pformat(plan)
|
||||||
return plan
|
return plan
|
||||||
|
|
||||||
def delete(self):
|
def delete(self, safe=False):
|
||||||
"""Delete the documents matched by the query.
|
"""Delete the documents matched by the query.
|
||||||
|
|
||||||
|
:param safe: check if the operation succeeded before returning
|
||||||
"""
|
"""
|
||||||
self._collection.remove(self._query)
|
self._collection.remove(self._query, safe=safe)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _transform_update(cls, _doc_cls=None, **update):
|
def _transform_update(cls, _doc_cls=None, **update):
|
||||||
@ -402,6 +422,11 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def update(self, safe_update=True, **update):
|
def update(self, safe_update=True, **update):
|
||||||
"""Perform an atomic update on the fields matched by the query.
|
"""Perform an atomic update on the fields matched by the query.
|
||||||
|
|
||||||
|
:param safe: check if the operation succeeded before returning
|
||||||
|
:param update: Django-style update keyword arguments
|
||||||
|
|
||||||
|
.. versionadded:: 0.2
|
||||||
"""
|
"""
|
||||||
if pymongo.version < '1.1.1':
|
if pymongo.version < '1.1.1':
|
||||||
raise OperationError('update() method requires PyMongo 1.1.1+')
|
raise OperationError('update() method requires PyMongo 1.1.1+')
|
||||||
@ -417,6 +442,11 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def update_one(self, safe_update=True, **update):
|
def update_one(self, safe_update=True, **update):
|
||||||
"""Perform an atomic update on first field matched by the query.
|
"""Perform an atomic update on first field matched by the query.
|
||||||
|
|
||||||
|
:param safe: check if the operation succeeded before returning
|
||||||
|
:param update: Django-style update keyword arguments
|
||||||
|
|
||||||
|
.. versionadded:: 0.2
|
||||||
"""
|
"""
|
||||||
update = QuerySet._transform_update(self._document, **update)
|
update = QuerySet._transform_update(self._document, **update)
|
||||||
try:
|
try:
|
||||||
@ -442,6 +472,12 @@ class QuerySet(object):
|
|||||||
collection in use; ``query``, which is an object representing the
|
collection in use; ``query``, which is an object representing the
|
||||||
current query; and ``options``, which is an object containing any
|
current query; and ``options``, which is an object containing any
|
||||||
options specified as keyword arguments.
|
options specified as keyword arguments.
|
||||||
|
|
||||||
|
:param code: a string of Javascript code to execute
|
||||||
|
:param fields: fields that you will be using in your function, which
|
||||||
|
will be passed in to your function as arguments
|
||||||
|
:param options: options that you want available to the function
|
||||||
|
(accessed in Javascript through the ``options`` object)
|
||||||
"""
|
"""
|
||||||
fields = [QuerySet._translate_field_name(self._document, f)
|
fields = [QuerySet._translate_field_name(self._document, f)
|
||||||
for f in fields]
|
for f in fields]
|
||||||
@ -458,6 +494,9 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def sum(self, field):
|
def sum(self, field):
|
||||||
"""Sum over the values of the specified field.
|
"""Sum over the values of the specified field.
|
||||||
|
|
||||||
|
:param field: the field to sum over; use dot-notation to refer to
|
||||||
|
embedded document fields
|
||||||
"""
|
"""
|
||||||
sum_func = """
|
sum_func = """
|
||||||
function(sumField) {
|
function(sumField) {
|
||||||
@ -472,6 +511,9 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def average(self, field):
|
def average(self, field):
|
||||||
"""Average over the values of the specified field.
|
"""Average over the values of the specified field.
|
||||||
|
|
||||||
|
:param field: the field to average over; use dot-notation to refer to
|
||||||
|
embedded document fields
|
||||||
"""
|
"""
|
||||||
average_func = """
|
average_func = """
|
||||||
function(averageField) {
|
function(averageField) {
|
||||||
@ -492,6 +534,9 @@ class QuerySet(object):
|
|||||||
"""Returns a dictionary of all items present in a list field across
|
"""Returns a dictionary of all items present in a list field across
|
||||||
the whole queried set of documents, and their corresponding frequency.
|
the whole queried set of documents, and their corresponding frequency.
|
||||||
This is useful for generating tag clouds, or searching documents.
|
This is useful for generating tag clouds, or searching documents.
|
||||||
|
|
||||||
|
:param list_field: the list field to use
|
||||||
|
:param normalize: normalize the results so they add to 1.0
|
||||||
"""
|
"""
|
||||||
freq_func = """
|
freq_func = """
|
||||||
function(listField) {
|
function(listField) {
|
||||||
|
@ -245,6 +245,19 @@ class DocumentTest(unittest.TestCase):
|
|||||||
self.assertTrue([('_types', 1), ('category', 1), ('addDate', -1)]
|
self.assertTrue([('_types', 1), ('category', 1), ('addDate', -1)]
|
||||||
in info.values())
|
in info.values())
|
||||||
self.assertTrue([('_types', 1), ('addDate', -1)] in info.values())
|
self.assertTrue([('_types', 1), ('addDate', -1)] in info.values())
|
||||||
|
|
||||||
|
class ExtendedBlogPost(BlogPost):
|
||||||
|
title = StringField()
|
||||||
|
meta = {'indexes': ['title']}
|
||||||
|
|
||||||
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
list(ExtendedBlogPost.objects)
|
||||||
|
info = ExtendedBlogPost.objects._collection.index_information()
|
||||||
|
self.assertTrue([('_types', 1), ('category', 1), ('addDate', -1)]
|
||||||
|
in info.values())
|
||||||
|
self.assertTrue([('_types', 1), ('addDate', -1)] in info.values())
|
||||||
|
self.assertTrue([('_types', 1), ('title', 1)] in info.values())
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user