69 lines
2.2 KiB
Python
69 lines
2.2 KiB
Python
from functools import wraps
|
|
|
|
from reversion.compat import is_authenticated
|
|
from reversion.revisions import create_revision as create_revision_base, set_user, get_user
|
|
|
|
|
|
class _RollBackRevisionView(Exception):
|
|
|
|
def __init__(self, response):
|
|
self.response = response
|
|
|
|
|
|
def _request_creates_revision(request):
|
|
return request.method not in ("OPTIONS", "GET", "HEAD")
|
|
|
|
|
|
def _set_user_from_request(request):
|
|
if getattr(request, "user", None) and is_authenticated(request.user) and get_user() is None:
|
|
set_user(request.user)
|
|
|
|
|
|
def create_revision(manage_manually=False, using=None, atomic=True):
|
|
"""
|
|
View decorator that wraps the request in a revision.
|
|
|
|
The revision will have it's user set from the request automatically.
|
|
"""
|
|
def decorator(func):
|
|
@wraps(func)
|
|
def do_revision_view(request, *args, **kwargs):
|
|
if _request_creates_revision(request):
|
|
try:
|
|
with create_revision_base(manage_manually=manage_manually, using=using, atomic=atomic):
|
|
response = func(request, *args, **kwargs)
|
|
# Check for an error response.
|
|
if response.status_code >= 400:
|
|
raise _RollBackRevisionView(response)
|
|
# Otherwise, we're good.
|
|
_set_user_from_request(request)
|
|
return response
|
|
except _RollBackRevisionView as ex:
|
|
return ex.response
|
|
return func(request, *args, **kwargs)
|
|
return do_revision_view
|
|
return decorator
|
|
|
|
|
|
class RevisionMixin(object):
|
|
|
|
"""
|
|
A class-based view mixin that wraps the request in a revision.
|
|
|
|
The revision will have it's user set from the request automatically.
|
|
"""
|
|
|
|
revision_manage_manually = False
|
|
|
|
revision_using = None
|
|
|
|
revision_atomic = True
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(RevisionMixin, self).__init__(*args, **kwargs)
|
|
self.dispatch = create_revision(
|
|
manage_manually=self.revision_manage_manually,
|
|
using=self.revision_using,
|
|
atomic=self.revision_atomic
|
|
)(self.dispatch)
|