Login

Nested commit_on_success

Author:
rfk
Posted:
February 26, 2009
Language:
Python
Version:
1.0
Tags:
transaction
Score:
2 (after 2 ratings)

This is a simple modification to the standard transaction.commit_on_success decorator that is aware of existing transactions. If a managed transaction is already active then the wrapped function is called directly, assuming the active transaction will clean up as appropriate. Otherwise, a standard commit_on_success is performed.

I'm using this to wrap the save() method of models that manipulate other related models on save, e.g:

@nested_commit_on_success
def save(self):
    super(MyClass,self).save()
    for m in other_models:
        self.fix_up_other_model(m)
        m.save()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def nested_commit_on_success(func):
    """Like commit_on_success, but doesn't commit existing transactions.

    This decorator is used to run a function within the scope of a 
    database transaction, committing the transaction on success and
    rolling it back if an exception occurs.

    Unlike the standard transaction.commit_on_success decorator, this
    version first checks whether a transaction is already active.  If so
    then it doesn't perform any commits or rollbacks, leaving that up to
    whoever is managing the active transaction.
    """
    commit_on_success = transaction.commit_on_success(func)
    def _nested_commit_on_success(*args, **kwds):
        if transaction.is_managed():
            return func(*args,**kwds)
        else:
            return commit_on_success(*args,**kwds)
    return transaction.wraps(func)(_nested_commit_on_success)

More like this

  1. PositionField by jpwatts 6 years, 7 months ago
  2. Model Hooks by jakecr 5 years, 1 month ago
  3. django_bulk_save.py - defer saving of django models to bulk SQL commits by preetkukreti 5 years ago
  4. Memento by manelvf 4 years, 1 month ago
  5. RandomObjectManager by jjdelc 3 years, 12 months ago

Comments

demichej (on August 10, 2011):

Thanks, RFK! I love it! I wonder why Django doesn't just use this decorator instead of its normal commit_on_success() what am I missing? It seems like this works exactly like commit_on_success, except it won't open a new transaction if one is already being managed?

#

demanzano (on August 11, 2011):

Very useful!

just a question, this code is for a decorator (the '@' operator) but what if I would use the 'with' operator ? How should I modify this code to be run with 'with' ? Thanks anyway !

#

Please login first before commenting.