diff options
| -rw-r--r-- | django/db/backends/base/base.py | 11 | ||||
| -rw-r--r-- | docs/releases/1.9.7.txt | 3 | ||||
| -rw-r--r-- | tests/transaction_hooks/tests.py | 14 |
3 files changed, 22 insertions, 6 deletions
diff --git a/django/db/backends/base/base.py b/django/db/backends/base/base.py index 0356ab54cc..021fe0bafa 100644 --- a/django/db/backends/base/base.py +++ b/django/db/backends/base/base.py @@ -617,12 +617,11 @@ class BaseDatabaseWrapper(object): def run_and_clear_commit_hooks(self): self.validate_no_atomic_block() - try: - while self.run_on_commit: - sids, func = self.run_on_commit.pop(0) - func() - finally: - self.run_on_commit = [] + current_run_on_commit = self.run_on_commit + self.run_on_commit = [] + while current_run_on_commit: + sids, func = current_run_on_commit.pop(0) + func() def copy(self, alias=None, allow_thread_sharing=None): """ diff --git a/docs/releases/1.9.7.txt b/docs/releases/1.9.7.txt index 5514222888..2f5555721f 100644 --- a/docs/releases/1.9.7.txt +++ b/docs/releases/1.9.7.txt @@ -17,3 +17,6 @@ Bugfixes * Fixed a regression causing the cached template loader to crash when using lazy template names (:ticket:`26603`). + +* Fixed ``on_commit`` callbacks execution order when callbacks make + transactions (:ticket:`26627`). diff --git a/tests/transaction_hooks/tests.py b/tests/transaction_hooks/tests.py index ebf07bc656..000de4104c 100644 --- a/tests/transaction_hooks/tests.py +++ b/tests/transaction_hooks/tests.py @@ -208,6 +208,20 @@ class TestConnectionOnCommit(TransactionTestCase): self.assertDone([1]) + def test_hook_in_hook(self): + def on_commit(i, add_hook): + with transaction.atomic(): + if add_hook: + transaction.on_commit(lambda: on_commit(i + 10, False)) + t = Thing.objects.create(num=i) + self.notify(t.num) + + with transaction.atomic(): + transaction.on_commit(lambda: on_commit(1, True)) + transaction.on_commit(lambda: on_commit(2, True)) + + self.assertDone([1, 11, 2, 12]) + def test_raises_exception_non_autocommit_mode(self): def should_never_be_called(): raise AssertionError('this function should never be called') |
