def with_docstash(group=None):
def _decorator(view):
view_name = group or '.'.join((view.__module__, view.__name__))
@wraps(view)
def _inner(request, docstash_key=None, **kwargs):
if not docstash_key:
docstash = DocStash.objects.create(group=view_name, owner=request.user)
return redirect(view_name, docstash_key=docstash.key, **kwargs)
docstash = get_object_or_404(DocStash, group=view_name,
owner=request.user, key=docstash_key)
request.docstash = docstash
return view(request, **kwargs)
return _inner
return _decorator
python类wraps()的实例源码
def flag_check(flag_name, state, fallback=None, **fc_kwargs):
""" Check that a given flag has the given state.
If the state does not match, perform the fallback. """
def decorator(func):
def inner(request, *args, **kwargs):
enabled = flag_state(flag_name, request=request, **fc_kwargs)
if ((state and enabled) or (not state and not enabled)):
return func(request, *args, **kwargs)
elif fallback is not None:
return fallback(request, *args, **kwargs)
else:
raise Http404
return wraps(func)(inner)
return decorator
def user_passes_test(test_func, login_url=None,
redirect_field_name=REDIRECT_FIELD_NAME):
"""Replacement for django.contrib.auth.decorators.user_passes_test that
returns 403 Forbidden if the user is already logged in.
"""
if not login_url:
from django.conf import settings
login_url = settings.LOGIN_URL
def decorator(view_func):
@wraps(view_func)
def wrapper(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
elif request.user.is_authenticated():
return HttpResponseForbidden('<h1>Permission denied</h1>')
else:
path = '%s?%s=%s' % (login_url, redirect_field_name,
urlquote(request.get_full_path()))
return HttpResponseRedirect(path)
return wrapper
return decorator
def __call__(self, func):
@wraps(func)
def decorated(*args, **kwargs):
with self:
return func(*args, **kwargs)
return decorated
def _safety_decorator(safety_marker, func):
@wraps(func)
def wrapped(*args, **kwargs):
return safety_marker(func(*args, **kwargs))
return wrapped
def cache_it(expires=None, key_func=None):
if not expires:
expires = getattr(settings, 'VIMEO_CACHE_EXPIRES', 300)
cache = None
try:
cache_backend = getattr(settings, 'VIMEO_CACHE_BACKEND', None)
cache = caches[cache_backend]
except InvalidCacheBackendError as e:
logger.warning('Vimeo cache "VIMEO_CACHE_BACKEND" disabled, reason: {}'.format(e))
def wrap(f):
@wraps(f)
def wrapper(*args, **kwds):
if not cache:
return f(*args, **kwds)
if key_func:
key = 'django_vimeo_cache:{}'.format(key_func(*args, **kwds))
else:
key = 'django_vimeo_cache:' + f.__name__ + ':' +\
str(list(args) + list(sorted(kwds.items())))
key = xxhash.xxh64(key).hexdigest()
value = cache.get(key)
if value is None:
value = f(*args, **kwds)
cache.set(key, value, expires)
value = cache.get(key)
if value is None:
raise Exception('failed to fetch cached value, try again')
return value
return wrapper
return wrap
def _safety_decorator(safety_marker, func):
@wraps(func)
def wrapped(*args, **kwargs):
return safety_marker(func(*args, **kwargs))
return wrapped
def requires_post(redirect='alertprofiles-overview', required_args=None):
"""Decorates a view function to require a POST request.
If the view function was not reached via a POST request, a session
error message is generated, and the client is redirected to the
specified redirect view.
"""
def _required_args_are_present(request):
if required_args is not None:
for arg in required_args:
if not request.POST.get(arg):
return False
return True
def _decorator(func):
def _handler(request, *args, **kwargs):
error = None
if request.method == 'POST':
if _required_args_are_present(request):
return func(request, *args, **kwargs)
else:
error = _('Required post-data were not supplied')
else:
error = _('There was no post-data')
new_message(request, error, Messages.ERROR)
return HttpResponseRedirect(reverse(redirect))
return wraps(func)(_handler)
return _decorator
def to_thread(func):
@wraps(func)
def inner(*args, **kwargs):
queue.put((func, args, kwargs))
return inner
def __call__(self, test_func):
from django.test import TransactionTestCase
if isinstance(test_func, type):
if not issubclass(test_func, TransactionTestCase):
raise Exception(
"Only subclasses of Django SimpleTestCase "
"can be decorated with override_settings")
original_pre_setup = test_func._pre_setup
original_post_teardown = test_func._post_teardown
def _pre_setup(innerself):
self.enable()
original_pre_setup(innerself)
def _post_teardown(innerself):
original_post_teardown(innerself)
self.disable()
test_func._pre_setup = _pre_setup
test_func._post_teardown = _post_teardown
return test_func
else:
@wraps(test_func)
def inner(*args, **kwargs):
with self:
return test_func(*args, **kwargs)
return inner
def confirm_required(template_name, context_creator, key='__confirm__'):
"""
Decorator for views that need confirmation page. For example, delete
object view. Decorated view renders confirmation page defined by template
'template_name'. If request.POST contains confirmation key, defined
by 'key' parameter, then original view is executed.
Context for confirmation page is created by function 'context_creator',
which accepts same arguments as decorated view.
Example
-------
def remove_file_context(request, id):
file = get_object_or_404(Attachment, id=id)
return RequestContext(request, {'file': file})
@confirm_required('remove_file_confirm.html', remove_file_context)
def remove_file_view(request, id):
file = get_object_or_404(Attachment, id=id)
file.delete()
next_url = request.GET.get('next', '/')
return HttpResponseRedirect(next_url)
Example of HTML template
------------------------
<h1>Remove file {{ file }}?</h1>
<form method="POST" action="">
<input type="hidden" name="__confirm__" value="1" />
<input type="submit" value="delete"/>
<a href="{{ file.get_absolute_url }}">cancel</a>
</form>
Source: http://djangosnippets.org/snippets/1922/
"""
def decorator(func):
def inner(request, *args, **kwargs):
if key in request.POST:
return func(request, *args, **kwargs)
context = context_creator \
and context_creator(request, *args, **kwargs) \
or RequestContext(request)
return render_to_response(template_name, context)
return wraps(func)(inner)
return decorator