Cascading saves now default to off (#291)

This commit is contained in:
Ross Lawley 2013-04-25 10:24:33 +00:00
parent c60ea40828
commit fe62c3aacb
5 changed files with 58 additions and 40 deletions

View File

@ -4,6 +4,7 @@ Changelog
Changes in 0.8.X
================
- Cascading saves now default to off (#291)
- ReferenceField now store ObjectId's by default rather than DBRef (#290)
- Added ImageField support for inline replacements (#86)
- Added SequenceField.set_next_value(value) helper (#159)

View File

@ -5,11 +5,21 @@ Upgrading
0.7 to 0.8
**********
Inheritance
===========
There have been numerous backwards breaking changes in 0.8. The reasons for
these are ensure that MongoEngine has sane defaults going forward and
performs the best it can out the box. Where possible there have been
FutureWarnings to help get you ready for the change, but that hasn't been
possible for the whole of the release.
.. warning:: Breaking changes - test upgrading on a test system before putting
live. There maybe multiple manual steps in migrating and these are best honed
on a staging / test system.
Data Model
----------
==========
Inheritance
-----------
The inheritance model has changed, we no longer need to store an array of
:attr:`types` with the model we can just use the classname in :attr:`_cls`.
@ -105,6 +115,21 @@ eg::
p._mark_as_dirty('friends')
p.save()
Cascading Saves
---------------
To improve performance document saves will no longer automatically cascade.
Any changes to a Documents references will either have to be saved manually or
you will have to explicitly tell it to cascade on save::
# At the class level:
class Person(Document):
meta = {'cascade': True}
# Or on save:
my_document.save(cascade=True)
Querysets
=========

View File

@ -244,7 +244,6 @@ class Document(BaseDocument):
upsert=upsert, **write_concern)
created = is_new_object(last_error)
warn_cascade = not cascade and 'cascade' not in self._meta
cascade = (self._meta.get('cascade', True)
if cascade is None else cascade)
if cascade:
@ -257,7 +256,7 @@ class Document(BaseDocument):
if cascade_kwargs: # Allow granular control over cascades
kwargs.update(cascade_kwargs)
kwargs['_refs'] = _refs
self.cascade_save(warn_cascade=warn_cascade, **kwargs)
self.cascade_save(**kwargs)
except pymongo.errors.OperationFailure, err:
message = 'Could not save document (%s)'
@ -276,7 +275,7 @@ class Document(BaseDocument):
signals.post_save.send(self.__class__, document=self, created=created)
return self
def cascade_save(self, warn_cascade=None, *args, **kwargs):
def cascade_save(self, *args, **kwargs):
"""Recursively saves any references /
generic references on an objects"""
import fields
@ -296,10 +295,6 @@ class Document(BaseDocument):
ref_id = "%s,%s" % (ref.__class__.__name__, str(ref._data))
if ref and ref_id not in _refs:
if warn_cascade:
msg = ("Cascading saves will default to off in 0.8, "
"please explicitly set `.save(cascade=True)`")
warnings.warn(msg, FutureWarning)
_refs.append(ref_id)
kwargs["_refs"] = _refs
ref.save(**kwargs)

View File

@ -17,7 +17,7 @@ __all__ = ('AllWarnings', )
class AllWarnings(unittest.TestCase):
def setUp(self):
conn = connect(db='mongoenginetest')
connect(db='mongoenginetest')
self.warning_list = []
self.showwarning_default = warnings.showwarning
warnings.showwarning = self.append_to_warning_list
@ -30,31 +30,6 @@ class AllWarnings(unittest.TestCase):
# restore default handling of warnings
warnings.showwarning = self.showwarning_default
def test_document_save_cascade_future_warning(self):
class Person(Document):
name = StringField()
parent = ReferenceField('self')
Person.drop_collection()
p1 = Person(name="Wilson Snr")
p1.parent = None
p1.save()
p2 = Person(name="Wilson Jr")
p2.parent = p1
p2.parent.name = "Poppa Wilson"
p2.save()
self.assertTrue(len(self.warning_list) > 0)
if len(self.warning_list) > 1:
print self.warning_list
warning = self.warning_list[0]
self.assertEqual(FutureWarning, warning["category"])
self.assertTrue("Cascading saves will default to off in 0.8"
in str(warning["message"]))
def test_document_collection_syntax_warning(self):
class NonAbstractBase(Document):
@ -67,6 +42,3 @@ class AllWarnings(unittest.TestCase):
self.assertEqual(SyntaxWarning, warning["category"])
self.assertEqual('non_abstract_base',
InheritedDocumentFailTest._get_collection_name())
import sys
sys.path[0:0] = [""]

View File

@ -678,7 +678,7 @@ class InstanceTest(unittest.TestCase):
p1.reload()
self.assertEqual(p1.name, p.parent.name)
def test_save_cascade_meta(self):
def test_save_cascade_meta_false(self):
class Person(Document):
name = StringField()
@ -707,6 +707,31 @@ class InstanceTest(unittest.TestCase):
p1.reload()
self.assertEqual(p1.name, p.parent.name)
def test_save_cascade_meta_true(self):
class Person(Document):
name = StringField()
parent = ReferenceField('self')
meta = {'cascade': False}
Person.drop_collection()
p1 = Person(name="Wilson Snr")
p1.parent = None
p1.save()
p2 = Person(name="Wilson Jr")
p2.parent = p1
p2.save(cascade=True)
p = Person.objects(name="Wilson Jr").get()
p.parent.name = "Daddy Wilson"
p.save()
p1.reload()
self.assertNotEqual(p1.name, p.parent.name)
def test_save_cascades_generically(self):
class Person(Document):