Skip to content

Fix set_rollback for non_atomic_requests views - #10078

Open
majidkhazaei wants to merge 13 commits into
encode:mainfrom
majidkhazaei:fix-set-rollback-v2
Open

majidkhazaei wants to merge 13 commits into
encode:mainfrom
majidkhazaei:fix-set-rollback-v2

Conversation

@majidkhazaei

Copy link
Copy Markdown
Contributor

Summary

This PR re-implements the fix for #6921, superseding the work in #6922.

Per @auvipy's suggestion, this is a fresh PR directly against main
instead of continuing on the (now quite stale) #6922 branch.

What this changes

  1. set_rollback(request=None) — Mirrors Django's
    BaseHandler.make_view_atomic() logic. When a request is
    provided, it reads the resolved view's _non_atomic_requests
    attribute and skips databases that were explicitly excluded
    from ATOMIC_REQUESTS.

  2. RemovedInDRF321Warning — The old no-arg signature is
    deprecated but still works (best-effort fallback to the
    previous behavior).

  3. exception_handler — Now passes context.get('request')
    to set_rollback().

  4. Tests:

    • NonAtomicViewUnderTestCaseTests — proper regression test
      using TestCase (not TransactionTestCase), addressing
      Copilot's feedback that the previous test didn't actually
      reproduce the bug.
    • SetRollbackDeprecationTests — verifies the deprecation
      warning.
    • SetRollbackWithoutResolverMatchTests — verifies the
      fallback when resolver_match is missing
      (APIRequestFactory).
    • Updated existing tests to pass a request argument.

Why this is different from the current state of #6922

  • Uses TestCase instead of TransactionTestCase for the
    regression test, so it actually fails without the fix.
  • Preserves backward compatibility via an optional argument and
    deprecation warning.
  • Best-effort fallback when resolver_match is unavailable.
  • Avoids the extra hop through adamchainz:fix_issue_6921_atomic_requests.

Credit

Original design and analysis: @adamchainz, from the discussion
in #6921 and #6922. Thanks also to @auvipy and @lovelydinosaur
for the guidance.

Testing

All 11 tests in tests/test_atomic_requests.py pass.
Pre-commit is green.


Closes #6921.
Supersedes #6922.

adamchainz and others added 13 commits December 13, 2019 18:27
\## Description

Fixes encode#6921.

Added tests that fail before and pass afterwards.

Remove the check for `connection.in_atomic_block` to determine if the current request is under a `transaction.atomic` from `ATOMIC_REQUESTS`. Instead, duplicate the method that Django itself uses [in BaseHandler](https://github.com/django/django/blob/964dd4f4f208722d8993a35c1ff047d353cea1ea/django/core/handlers/base.py#L64).

This requires fetching the actual view function from `as_view()`, as seen by the URL resolver / BaseHandler. Since this requires `request`, I've also changed the accesses in `get_exception_handler_context` to be direct attribute accesses rather than `getattr()`. It seems the `getattr` defaults not accessible since `self.request`, `self.args`, and `self.kwargs` are always set in `dispatch()` before `handle_exception()` can ever be called. This is useful since `request` is always needed for the new `set_rollback` logic.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
# Conflicts:
#	rest_framework/views.py
#	tests/test_atomic_requests.py
set_rollback() now mirrors Django's BaseHandler.make_view_atomic()
logic: when a request is provided, it reads the resolved view's
_non_atomic_requests attribute and skips databases that were
explicitly excluded from ATOMIC_REQUESTS. This prevents DRF from
marking outer transactions (e.g. Django's TestCase wrapper) for
rollback when an APIException is raised from a @non_atomic_requests
view.

The previous signature set_rollback() is deprecated and will emit
a RemovedInDRF321Warning. It falls back to the old
ATOMIC_REQUESTS + in_atomic_block behavior.

Refs encode#6921, encode#6922.
@auvipy
auvipy requested review from auvipy and browniebroke October 14, 2026 13:15

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

set_rollback's atomic check is inaccurate

4 participants