Compare commits

..

3 Commits

Author SHA1 Message Date
Stefan Wojcik
3c8e1e5336 clean up the Document._get_collection code 2017-04-30 14:11:03 -04:00
Artemiy
bd4a603e16 Use De Morgan's laws to simplify an expression. (#1531) 2017-04-20 10:27:37 -04:00
Jason
358b80d782 Make the tutorial slightly more intuitive (#1530) 2017-04-20 09:11:38 -04:00
4 changed files with 59 additions and 38 deletions

View File

@@ -206,7 +206,10 @@ object::
ross.last_name = 'Lawley' ross.last_name = 'Lawley'
ross.save() ross.save()
Now that we've got our user in the database, let's add a couple of posts:: Assign another user to a variable called ``john``, just like we did above with
``ross``.
Now that we've got our users in the database, let's add a couple of posts::
post1 = TextPost(title='Fun with MongoEngine', author=john) post1 = TextPost(title='Fun with MongoEngine', author=john)
post1.content = 'Took a look at MongoEngine today, looks pretty cool.' post1.content = 'Took a look at MongoEngine today, looks pretty cool.'

View File

@@ -1,6 +1,6 @@
import copy import copy
import numbers import numbers
from collections.abc import Hashable from collections import Hashable
from functools import partial from functools import partial
from bson import ObjectId, json_util from bson import ObjectId, json_util

View File

@@ -167,45 +167,63 @@ class Document(BaseDocument):
@classmethod @classmethod
def _get_collection(cls): def _get_collection(cls):
"""Returns the collection for the document.""" """Return a PyMongo collection for the document."""
# TODO: use new get_collection() with PyMongo3 ?
if not hasattr(cls, '_collection') or cls._collection is None: if not hasattr(cls, '_collection') or cls._collection is None:
db = cls._get_db()
collection_name = cls._get_collection_name()
# Create collection as a capped collection if specified
if cls._meta.get('max_size') or cls._meta.get('max_documents'):
# Get max document limit and max byte size from meta
max_size = cls._meta.get('max_size') or 10 * 2 ** 20 # 10MB default
max_documents = cls._meta.get('max_documents')
# Round up to next 256 bytes as MongoDB would do it to avoid exception
if max_size % 256:
max_size = (max_size // 256 + 1) * 256
if collection_name in db.collection_names(): # Get the collection, either capped or regular.
cls._collection = db[collection_name] if cls._meta.get('max_size') or cls._meta.get('max_documents'):
# The collection already exists, check if its capped cls._collection = cls._get_capped_collection()
# options match the specified capped options
options = cls._collection.options()
if options.get('max') != max_documents or \
options.get('size') != max_size:
msg = (('Cannot create collection "%s" as a capped '
'collection as it already exists')
% cls._collection)
raise InvalidCollectionError(msg)
else:
# Create the collection as a capped collection
opts = {'capped': True, 'size': max_size}
if max_documents:
opts['max'] = max_documents
cls._collection = db.create_collection(
collection_name, **opts
)
else: else:
db = cls._get_db()
collection_name = cls._get_collection_name()
cls._collection = db[collection_name] cls._collection = db[collection_name]
# Ensure indexes on the collection unless auto_create_index was
# set to False.
if cls._meta.get('auto_create_index', True): if cls._meta.get('auto_create_index', True):
cls.ensure_indexes() cls.ensure_indexes()
return cls._collection return cls._collection
@classmethod
def _get_capped_collection(cls):
"""Create a new or get an existing capped PyMongo collection."""
db = cls._get_db()
collection_name = cls._get_collection_name()
# Get max document limit and max byte size from meta.
max_size = cls._meta.get('max_size') or 10 * 2 ** 20 # 10MB default
max_documents = cls._meta.get('max_documents')
# MongoDB will automatically raise the size to make it a multiple of
# 256 bytes. We raise it here ourselves to be able to reliably compare
# the options below.
if max_size % 256:
max_size = (max_size // 256 + 1) * 256
# If the collection already exists and has different options
# (i.e. isn't capped or has different max/size), raise an error.
if collection_name in db.collection_names():
collection = db[collection_name]
options = collection.options()
if (
options.get('max') != max_documents or
options.get('size') != max_size
):
raise InvalidCollectionError(
'Cannot create collection "{}" as a capped '
'collection as it already exists'.format(cls._collection)
)
return collection
# Create a new capped collection.
opts = {'capped': True, 'size': max_size}
if max_documents:
opts['max'] = max_documents
return db.create_collection(collection_name, **opts)
def to_mongo(self, *args, **kwargs): def to_mongo(self, *args, **kwargs):
data = super(Document, self).to_mongo(*args, **kwargs) data = super(Document, self).to_mongo(*args, **kwargs)
@@ -808,7 +826,7 @@ class Document(BaseDocument):
collection = cls._get_collection() collection = cls._get_collection()
# 746: when connection is via mongos, the read preference is not necessarily an indication that # 746: when connection is via mongos, the read preference is not necessarily an indication that
# this code runs on a secondary # this code runs on a secondary
if collection.is_mongos is not None and collection.read_preference.mode > 1: if not collection.is_mongos and collection.read_preference > 1:
return return
# determine if an index which we are creating includes # determine if an index which we are creating includes

View File

@@ -6,7 +6,7 @@ import socket
import time import time
import uuid import uuid
import warnings import warnings
from collections.abc import Mapping from collections import Mapping
from operator import itemgetter from operator import itemgetter
from bson import Binary, DBRef, ObjectId, SON from bson import Binary, DBRef, ObjectId, SON
@@ -608,9 +608,9 @@ class EmbeddedDocumentField(BaseField):
""" """
def __init__(self, document_type, **kwargs): def __init__(self, document_type, **kwargs):
if ( if not (
not isinstance(document_type, six.string_types) and isinstance(document_type, six.string_types) or
not issubclass(document_type, EmbeddedDocument) issubclass(document_type, EmbeddedDocument)
): ):
self.error('Invalid embedded document class provided to an ' self.error('Invalid embedded document class provided to an '
'EmbeddedDocumentField') 'EmbeddedDocumentField')