Compare commits
10 Commits
cant-save-
...
test-write
Author | SHA1 | Date | |
---|---|---|---|
|
3e44ca4577 | ||
|
d378bd09a5 | ||
|
2ee8984b44 | ||
|
b7ec587e5b | ||
|
47c58bce2b | ||
|
96e95ac533 | ||
|
b013a065f7 | ||
|
c6cc013617 | ||
|
f4e1d80a87 | ||
|
91dad4060f |
18
README.rst
18
README.rst
@@ -57,7 +57,7 @@ Some simple examples of what MongoEngine code looks like:
|
|||||||
|
|
||||||
class BlogPost(Document):
|
class BlogPost(Document):
|
||||||
title = StringField(required=True, max_length=200)
|
title = StringField(required=True, max_length=200)
|
||||||
posted = DateTimeField(default=datetime.datetime.now)
|
posted = DateTimeField(default=datetime.datetime.utcnow)
|
||||||
tags = ListField(StringField(max_length=50))
|
tags = ListField(StringField(max_length=50))
|
||||||
meta = {'allow_inheritance': True}
|
meta = {'allow_inheritance': True}
|
||||||
|
|
||||||
@@ -87,17 +87,18 @@ Some simple examples of what MongoEngine code looks like:
|
|||||||
... print
|
... print
|
||||||
...
|
...
|
||||||
|
|
||||||
>>> len(BlogPost.objects)
|
# Count all blog posts and its subtypes
|
||||||
|
>>> BlogPost.objects.count()
|
||||||
2
|
2
|
||||||
>>> len(TextPost.objects)
|
>>> TextPost.objects.count()
|
||||||
1
|
1
|
||||||
>>> len(LinkPost.objects)
|
>>> LinkPost.objects.count()
|
||||||
1
|
1
|
||||||
|
|
||||||
# Find tagged posts
|
# Count tagged posts
|
||||||
>>> len(BlogPost.objects(tags='mongoengine'))
|
>>> BlogPost.objects(tags='mongoengine').count()
|
||||||
2
|
2
|
||||||
>>> len(BlogPost.objects(tags='mongodb'))
|
>>> BlogPost.objects(tags='mongodb').count()
|
||||||
1
|
1
|
||||||
|
|
||||||
Tests
|
Tests
|
||||||
@@ -130,8 +131,7 @@ Community
|
|||||||
<http://groups.google.com/group/mongoengine-users>`_
|
<http://groups.google.com/group/mongoengine-users>`_
|
||||||
- `MongoEngine Developers mailing list
|
- `MongoEngine Developers mailing list
|
||||||
<http://groups.google.com/group/mongoengine-dev>`_
|
<http://groups.google.com/group/mongoengine-dev>`_
|
||||||
- `#mongoengine IRC channel <http://webchat.freenode.net/?channels=mongoengine>`_
|
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
============
|
============
|
||||||
We welcome contributions! see the `Contribution guidelines <https://github.com/MongoEngine/mongoengine/blob/master/CONTRIBUTING.rst>`_
|
We welcome contributions! See the `Contribution guidelines <https://github.com/MongoEngine/mongoengine/blob/master/CONTRIBUTING.rst>`_
|
||||||
|
@@ -33,7 +33,7 @@ the :attr:`host` to
|
|||||||
corresponding parameters in :func:`~mongoengine.connect`: ::
|
corresponding parameters in :func:`~mongoengine.connect`: ::
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
name='test',
|
db='test',
|
||||||
username='user',
|
username='user',
|
||||||
password='12345',
|
password='12345',
|
||||||
host='mongodb://admin:qwerty@localhost/production'
|
host='mongodb://admin:qwerty@localhost/production'
|
||||||
|
@@ -5,7 +5,7 @@ __all__ = ('UPDATE_OPERATORS', 'get_document', '_document_registry')
|
|||||||
|
|
||||||
UPDATE_OPERATORS = set(['set', 'unset', 'inc', 'dec', 'pop', 'push',
|
UPDATE_OPERATORS = set(['set', 'unset', 'inc', 'dec', 'pop', 'push',
|
||||||
'push_all', 'pull', 'pull_all', 'add_to_set',
|
'push_all', 'pull', 'pull_all', 'add_to_set',
|
||||||
'set_on_insert', 'min', 'max'])
|
'set_on_insert', 'min', 'max', 'rename'])
|
||||||
|
|
||||||
|
|
||||||
_document_registry = {}
|
_document_registry = {}
|
||||||
|
@@ -402,9 +402,11 @@ class BaseDocument(object):
|
|||||||
raise ValidationError(message, errors=errors)
|
raise ValidationError(message, errors=errors)
|
||||||
|
|
||||||
def to_json(self, *args, **kwargs):
|
def to_json(self, *args, **kwargs):
|
||||||
"""Converts a document to JSON.
|
"""Convert this document to JSON.
|
||||||
:param use_db_field: Set to True by default but enables the output of the json structure with the field names
|
|
||||||
and not the mongodb store db_names in case of set to False
|
:param use_db_field: Serialize field names as they appear in
|
||||||
|
MongoDB (as opposed to attribute names on this document).
|
||||||
|
Defaults to True.
|
||||||
"""
|
"""
|
||||||
use_db_field = kwargs.pop('use_db_field', True)
|
use_db_field = kwargs.pop('use_db_field', True)
|
||||||
return json_util.dumps(self.to_mongo(use_db_field), *args, **kwargs)
|
return json_util.dumps(self.to_mongo(use_db_field), *args, **kwargs)
|
||||||
|
@@ -313,6 +313,9 @@ class Document(BaseDocument):
|
|||||||
.. versionchanged:: 0.10.7
|
.. versionchanged:: 0.10.7
|
||||||
Add signal_kwargs argument
|
Add signal_kwargs argument
|
||||||
"""
|
"""
|
||||||
|
if self._meta.get('abstract'):
|
||||||
|
raise InvalidDocumentError('Cannot save an abstract document.')
|
||||||
|
|
||||||
signal_kwargs = signal_kwargs or {}
|
signal_kwargs = signal_kwargs or {}
|
||||||
signals.pre_save.send(self.__class__, document=self, **signal_kwargs)
|
signals.pre_save.send(self.__class__, document=self, **signal_kwargs)
|
||||||
|
|
||||||
@@ -828,7 +831,6 @@ class Document(BaseDocument):
|
|||||||
""" Lists all of the indexes that should be created for given
|
""" Lists all of the indexes that should be created for given
|
||||||
collection. It includes all the indexes from super- and sub-classes.
|
collection. It includes all the indexes from super- and sub-classes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if cls._meta.get('abstract'):
|
if cls._meta.get('abstract'):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@@ -933,7 +933,20 @@ class BaseQuerySet(object):
|
|||||||
key = '.'.join(parts)
|
key = '.'.join(parts)
|
||||||
cleaned_fields.append((key, value))
|
cleaned_fields.append((key, value))
|
||||||
|
|
||||||
fields = sorted(cleaned_fields, key=operator.itemgetter(1))
|
# Sort fields by their values, explicitly excluded fields first, then
|
||||||
|
# explicitly included, and then more complicated operators such as
|
||||||
|
# $slice.
|
||||||
|
def _sort_key(field_tuple):
|
||||||
|
key, value = field_tuple
|
||||||
|
if isinstance(value, (int)):
|
||||||
|
return value # 0 for exclusion, 1 for inclusion
|
||||||
|
else:
|
||||||
|
return 2 # so that complex values appear last
|
||||||
|
|
||||||
|
fields = sorted(cleaned_fields, key=_sort_key)
|
||||||
|
|
||||||
|
# Clone the queryset, group all fields by their value, convert
|
||||||
|
# each of them to db_fields, and set the queryset's _loaded_fields
|
||||||
queryset = self.clone()
|
queryset = self.clone()
|
||||||
for value, group in itertools.groupby(fields, lambda x: x[1]):
|
for value, group in itertools.groupby(fields, lambda x: x[1]):
|
||||||
fields = [field for field, value in group]
|
fields = [field for field, value in group]
|
||||||
|
@@ -233,7 +233,6 @@ def update(_doc_cls=None, **update):
|
|||||||
# Support decrement by flipping a positive value's sign
|
# Support decrement by flipping a positive value's sign
|
||||||
# and using 'inc'
|
# and using 'inc'
|
||||||
op = 'inc'
|
op = 'inc'
|
||||||
if value > 0:
|
|
||||||
value = -value
|
value = -value
|
||||||
elif op == 'add_to_set':
|
elif op == 'add_to_set':
|
||||||
op = 'addToSet'
|
op = 'addToSet'
|
||||||
|
@@ -435,6 +435,15 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
person.to_dbref()
|
person.to_dbref()
|
||||||
|
|
||||||
|
def test_save_abstract_document(self):
|
||||||
|
"""Saving an abstract document should fail."""
|
||||||
|
class Doc(Document):
|
||||||
|
name = StringField()
|
||||||
|
meta = {'abstract': True}
|
||||||
|
|
||||||
|
with self.assertRaises(InvalidDocumentError):
|
||||||
|
Doc(name='aaa').save()
|
||||||
|
|
||||||
def test_reload(self):
|
def test_reload(self):
|
||||||
"""Ensure that attributes may be reloaded.
|
"""Ensure that attributes may be reloaded.
|
||||||
"""
|
"""
|
||||||
@@ -1223,6 +1232,19 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(person.name, None)
|
self.assertEqual(person.name, None)
|
||||||
self.assertEqual(person.age, None)
|
self.assertEqual(person.age, None)
|
||||||
|
|
||||||
|
def test_update_rename_operator(self):
|
||||||
|
"""Test the $rename operator."""
|
||||||
|
coll = self.Person._get_collection()
|
||||||
|
doc = self.Person(name='John').save()
|
||||||
|
raw_doc = coll.find_one({'_id': doc.pk})
|
||||||
|
self.assertEqual(set(raw_doc.keys()), set(['_id', '_cls', 'name']))
|
||||||
|
|
||||||
|
doc.update(rename__name='first_name')
|
||||||
|
raw_doc = coll.find_one({'_id': doc.pk})
|
||||||
|
self.assertEqual(set(raw_doc.keys()),
|
||||||
|
set(['_id', '_cls', 'first_name']))
|
||||||
|
self.assertEqual(raw_doc['first_name'], 'John')
|
||||||
|
|
||||||
def test_inserts_if_you_set_the_pk(self):
|
def test_inserts_if_you_set_the_pk(self):
|
||||||
p1 = self.Person(name='p1', id=bson.ObjectId()).save()
|
p1 = self.Person(name='p1', id=bson.ObjectId()).save()
|
||||||
p2 = self.Person(name='p2')
|
p2 = self.Person(name='p2')
|
||||||
|
@@ -141,6 +141,16 @@ class OnlyExcludeAllTest(unittest.TestCase):
|
|||||||
self.assertEqual(qs._loaded_fields.as_dict(),
|
self.assertEqual(qs._loaded_fields.as_dict(),
|
||||||
{'b': {'$slice': 5}})
|
{'b': {'$slice': 5}})
|
||||||
|
|
||||||
|
def test_mix_slice_with_other_fields(self):
|
||||||
|
class MyDoc(Document):
|
||||||
|
a = ListField()
|
||||||
|
b = ListField()
|
||||||
|
c = ListField()
|
||||||
|
|
||||||
|
qs = MyDoc.objects.fields(a=1, b=0, slice__c=2)
|
||||||
|
self.assertEqual(qs._loaded_fields.as_dict(),
|
||||||
|
{'c': {'$slice': 2}, 'a': 1})
|
||||||
|
|
||||||
def test_only(self):
|
def test_only(self):
|
||||||
"""Ensure that QuerySet.only only returns the requested fields.
|
"""Ensure that QuerySet.only only returns the requested fields.
|
||||||
"""
|
"""
|
||||||
|
@@ -1826,6 +1826,11 @@ class QuerySetTest(unittest.TestCase):
|
|||||||
post.reload()
|
post.reload()
|
||||||
self.assertEqual(post.hits, 10)
|
self.assertEqual(post.hits, 10)
|
||||||
|
|
||||||
|
# Negative dec operator is equal to a positive inc operator
|
||||||
|
BlogPost.objects.update_one(dec__hits=-1)
|
||||||
|
post.reload()
|
||||||
|
self.assertEqual(post.hits, 11)
|
||||||
|
|
||||||
BlogPost.objects.update(push__tags='mongo')
|
BlogPost.objects.update(push__tags='mongo')
|
||||||
post.reload()
|
post.reload()
|
||||||
self.assertTrue('mongo' in post.tags)
|
self.assertTrue('mongo' in post.tags)
|
||||||
|
@@ -296,6 +296,19 @@ class ConnectionTest(unittest.TestCase):
|
|||||||
conn = get_connection('t2')
|
conn = get_connection('t2')
|
||||||
self.assertFalse(get_tz_awareness(conn))
|
self.assertFalse(get_tz_awareness(conn))
|
||||||
|
|
||||||
|
def test_write_concern(self):
|
||||||
|
"""Ensure write concern can be specified in connect() via
|
||||||
|
a kwarg or as part of the connection URI.
|
||||||
|
"""
|
||||||
|
conn1 = connect(alias='conn1', host='mongodb://localhost/testing?w=1&j=true')
|
||||||
|
conn2 = connect('testing', alias='conn2', w=1, j=True)
|
||||||
|
if IS_PYMONGO_3:
|
||||||
|
self.assertEqual(conn1.write_concern.document, {'w': 1, 'j': True})
|
||||||
|
self.assertEqual(conn2.write_concern.document, {'w': 1, 'j': True})
|
||||||
|
else:
|
||||||
|
self.assertEqual(dict(conn1.write_concern), {'w': 1, 'j': True})
|
||||||
|
self.assertEqual(dict(conn2.write_concern), {'w': 1, 'j': True})
|
||||||
|
|
||||||
def test_datetime(self):
|
def test_datetime(self):
|
||||||
connect('mongoenginetest', tz_aware=True)
|
connect('mongoenginetest', tz_aware=True)
|
||||||
d = datetime.datetime(2010, 5, 5, tzinfo=utc)
|
d = datetime.datetime(2010, 5, 5, tzinfo=utc)
|
||||||
|
Reference in New Issue
Block a user