Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Unreleased
- Made ``bulk_update_with_history()`` return the number of model rows updated (gh-1206)
- Fixed ``HistoryRequestMiddleware`` not cleaning up after itself (i.e. deleting
``HistoricalRecords.context.request``) under some circumstances (gh-1188)
- Made ``HistoryRequestMiddleware`` async-capable (gh-1209)

3.3.0 (2023-03-08)
------------------
Expand Down
43 changes: 30 additions & 13 deletions simple_history/middleware.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
from contextlib import contextmanager

from asgiref.sync import iscoroutinefunction
from django.utils.decorators import sync_and_async_middleware

from .models import HistoricalRecords


class HistoryRequestMiddleware:
@contextmanager
def _context_manager(request):
HistoricalRecords.context.request = request

try:
yield None
finally:
del HistoricalRecords.context.request


@sync_and_async_middleware
def HistoryRequestMiddleware(get_response):
"""Expose request to HistoricalRecords.

This middleware sets request as a local context/thread variable, making it
available to the model-level utilities to allow tracking of the authenticated user
making a change.
"""

def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
HistoricalRecords.context.request = request
try:
response = self.get_response(request)
except Exception as e:
raise e
finally:
del HistoricalRecords.context.request
return response
if iscoroutinefunction(get_response):

async def middleware(request):
with _context_manager(request):
return await get_response(request)

else:

def middleware(request):
with _context_manager(request):
return get_response(request)

return middleware