Fixed cascading saves which weren't turned off as planned (#291)
This commit is contained in:
parent
d935b5764a
commit
7451244cd2
@ -5,6 +5,7 @@ Changelog
|
|||||||
|
|
||||||
Changes in 0.8.2
|
Changes in 0.8.2
|
||||||
================
|
================
|
||||||
|
- Fixed cascading saves which weren't turned off as planned (#291)
|
||||||
- Fixed Datastructures so instances are a Document or EmbeddedDocument (#363)
|
- Fixed Datastructures so instances are a Document or EmbeddedDocument (#363)
|
||||||
- Improved cascading saves write performance (#361)
|
- Improved cascading saves write performance (#361)
|
||||||
- Fixed amibiguity and differing behaviour regarding field defaults (#349)
|
- Fixed amibiguity and differing behaviour regarding field defaults (#349)
|
||||||
|
@ -97,14 +97,6 @@ class DocumentMetaclass(type):
|
|||||||
attrs['_reverse_db_field_map'] = dict(
|
attrs['_reverse_db_field_map'] = dict(
|
||||||
(v, k) for k, v in attrs['_db_field_map'].iteritems())
|
(v, k) for k, v in attrs['_db_field_map'].iteritems())
|
||||||
|
|
||||||
# Set cascade flag if not set
|
|
||||||
if 'cascade' not in attrs['_meta']:
|
|
||||||
ReferenceField = _import_class('ReferenceField')
|
|
||||||
GenericReferenceField = _import_class('GenericReferenceField')
|
|
||||||
cascade = any([isinstance(x, (ReferenceField, GenericReferenceField))
|
|
||||||
for x in doc_fields.values()])
|
|
||||||
attrs['_meta']['cascade'] = cascade
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Set document hierarchy
|
# Set document hierarchy
|
||||||
#
|
#
|
||||||
|
@ -186,8 +186,8 @@ class Document(BaseDocument):
|
|||||||
will force an fsync on the primary server.
|
will force an fsync on the primary server.
|
||||||
:param cascade: Sets the flag for cascading saves. You can set a
|
:param cascade: Sets the flag for cascading saves. You can set a
|
||||||
default by setting "cascade" in the document __meta__
|
default by setting "cascade" in the document __meta__
|
||||||
:param cascade_kwargs: optional kwargs dictionary to be passed throw
|
:param cascade_kwargs: (optional) kwargs dictionary to be passed throw
|
||||||
to cascading saves
|
to cascading saves. Implies ``cascade=True``.
|
||||||
:param _refs: A list of processed references used in cascading saves
|
:param _refs: A list of processed references used in cascading saves
|
||||||
|
|
||||||
.. versionchanged:: 0.5
|
.. versionchanged:: 0.5
|
||||||
@ -196,11 +196,13 @@ class Document(BaseDocument):
|
|||||||
:class:`~bson.dbref.DBRef` objects that have changes are
|
:class:`~bson.dbref.DBRef` objects that have changes are
|
||||||
saved as well.
|
saved as well.
|
||||||
.. versionchanged:: 0.6
|
.. versionchanged:: 0.6
|
||||||
Cascade saves are optional = defaults to True, if you want
|
Added cascading saves
|
||||||
|
.. versionchanged:: 0.8
|
||||||
|
Cascade saves are optional and default to False. If you want
|
||||||
fine grain control then you can turn off using document
|
fine grain control then you can turn off using document
|
||||||
meta['cascade'] = False Also you can pass different kwargs to
|
meta['cascade'] = True. Also you can pass different kwargs to
|
||||||
the cascade save using cascade_kwargs which overwrites the
|
the cascade save using cascade_kwargs which overwrites the
|
||||||
existing kwargs with custom values
|
existing kwargs with custom values.
|
||||||
"""
|
"""
|
||||||
signals.pre_save.send(self.__class__, document=self)
|
signals.pre_save.send(self.__class__, document=self)
|
||||||
|
|
||||||
@ -251,8 +253,10 @@ class Document(BaseDocument):
|
|||||||
upsert=True, **write_concern)
|
upsert=True, **write_concern)
|
||||||
created = is_new_object(last_error)
|
created = is_new_object(last_error)
|
||||||
|
|
||||||
cascade = (self._meta.get('cascade', True)
|
|
||||||
if cascade is None else cascade)
|
if cascade is None:
|
||||||
|
cascade = self._meta.get('cascade', False) or cascade_kwargs is not None
|
||||||
|
|
||||||
if cascade:
|
if cascade:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"force_insert": force_insert,
|
"force_insert": force_insert,
|
||||||
|
@ -647,22 +647,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(b.picture, b.bar.picture, b.bar.bar.picture)
|
self.assertEqual(b.picture, b.bar.picture, b.bar.bar.picture)
|
||||||
|
|
||||||
def test_setting_cascade(self):
|
|
||||||
|
|
||||||
class ForcedCascade(Document):
|
|
||||||
meta = {'cascade': True}
|
|
||||||
|
|
||||||
class Feed(Document):
|
|
||||||
name = StringField()
|
|
||||||
|
|
||||||
class Subscription(Document):
|
|
||||||
name = StringField()
|
|
||||||
feed = ReferenceField(Feed)
|
|
||||||
|
|
||||||
self.assertTrue(ForcedCascade._meta['cascade'])
|
|
||||||
self.assertTrue(Subscription._meta['cascade'])
|
|
||||||
self.assertFalse(Feed._meta['cascade'])
|
|
||||||
|
|
||||||
def test_save_cascades(self):
|
def test_save_cascades(self):
|
||||||
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
@ -681,7 +665,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
p = Person.objects(name="Wilson Jr").get()
|
p = Person.objects(name="Wilson Jr").get()
|
||||||
p.parent.name = "Daddy Wilson"
|
p.parent.name = "Daddy Wilson"
|
||||||
p.save()
|
p.save(cascade=True)
|
||||||
|
|
||||||
p1.reload()
|
p1.reload()
|
||||||
self.assertEqual(p1.name, p.parent.name)
|
self.assertEqual(p1.name, p.parent.name)
|
||||||
@ -700,14 +684,12 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
p2 = Person(name="Wilson Jr")
|
p2 = Person(name="Wilson Jr")
|
||||||
p2.parent = p1
|
p2.parent = p1
|
||||||
|
p1.name = "Daddy Wilson"
|
||||||
p2.save(force_insert=True, cascade_kwargs={"force_insert": False})
|
p2.save(force_insert=True, cascade_kwargs={"force_insert": False})
|
||||||
|
|
||||||
p = Person.objects(name="Wilson Jr").get()
|
|
||||||
p.parent.name = "Daddy Wilson"
|
|
||||||
p.save()
|
|
||||||
|
|
||||||
p1.reload()
|
p1.reload()
|
||||||
self.assertEqual(p1.name, p.parent.name)
|
p2.reload()
|
||||||
|
self.assertEqual(p1.name, p2.parent.name)
|
||||||
|
|
||||||
def test_save_cascade_meta_false(self):
|
def test_save_cascade_meta_false(self):
|
||||||
|
|
||||||
@ -782,6 +764,10 @@ class InstanceTest(unittest.TestCase):
|
|||||||
p.parent.name = "Daddy Wilson"
|
p.parent.name = "Daddy Wilson"
|
||||||
p.save()
|
p.save()
|
||||||
|
|
||||||
|
p1.reload()
|
||||||
|
self.assertNotEqual(p1.name, p.parent.name)
|
||||||
|
|
||||||
|
p.save(cascade=True)
|
||||||
p1.reload()
|
p1.reload()
|
||||||
self.assertEqual(p1.name, p.parent.name)
|
self.assertEqual(p1.name, p.parent.name)
|
||||||
|
|
||||||
@ -1057,8 +1043,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
Feed.drop_collection()
|
Feed.drop_collection()
|
||||||
UserSubscription.drop_collection()
|
UserSubscription.drop_collection()
|
||||||
|
|
||||||
self.assertTrue(UserSubscription._meta['cascade'])
|
|
||||||
|
|
||||||
o1 = Organization(name="o1").save()
|
o1 = Organization(name="o1").save()
|
||||||
o2 = Organization(name="o2").save()
|
o2 = Organization(name="o2").save()
|
||||||
|
|
||||||
@ -1090,7 +1074,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(q, 1)
|
self.assertEqual(q, 1)
|
||||||
sub.user.name = "Test"
|
sub.user.name = "Test"
|
||||||
self.assertEqual(q, 2)
|
self.assertEqual(q, 2)
|
||||||
sub.save()
|
sub.save(cascade=True)
|
||||||
self.assertEqual(q, 3)
|
self.assertEqual(q, 3)
|
||||||
|
|
||||||
# Changing a value and one that will cascade
|
# Changing a value and one that will cascade
|
||||||
@ -1101,7 +1085,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(q, 1)
|
self.assertEqual(q, 1)
|
||||||
sub.user.name = "Test 2"
|
sub.user.name = "Test 2"
|
||||||
self.assertEqual(q, 2)
|
self.assertEqual(q, 2)
|
||||||
sub.save()
|
sub.save(cascade=True)
|
||||||
self.assertEqual(q, 4) # One for the UserSub and one for the User
|
self.assertEqual(q, 4) # One for the UserSub and one for the User
|
||||||
|
|
||||||
# Saving with just the refs
|
# Saving with just the refs
|
||||||
|
Loading…
x
Reference in New Issue
Block a user