Created
August 5, 2013 19:59
-
-
Save OEP/6159054 to your computer and use it in GitHub Desktop.
Extensible Django view decorator for confirming things before doing them.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Extensible confirmation decorator. | |
Simply decorate a view with @confirmation_required and a generic "check the | |
box" confirmation will show up. | |
By default the decorator passes the variables "title", "question", "prompt", | |
"form" and "error" to the template. Additional variables and overrides may be | |
specifies by passing a dict as the context parameter. | |
You may wish to do advanced stuff like fetching things from the database based | |
on which view was triggered. To do this, you'll have to provide processors for | |
the template arguments. A processor will be passed the template parameter in | |
the context as the first argument, and the arguments to the view as *args and | |
**kwargs. Here's an example for clarity: | |
def process_title(title, *args, **kwargs): | |
pk = kwargs['pk'] | |
person = Person.objects.get(pk=pk) | |
return title.format(name=person.first_name) | |
@confirmation_required(context={"title":"Really delete {name}?"}, | |
processors={title:process_title}) | |
def delete_person(request, pk): | |
Person.objects.delete(pk=pk) | |
""" | |
__all__ = ["confirmation_required"] | |
from django.utils.translation import ugettext_lazy as _ | |
from django.template import RequestContext | |
from django.shortcuts import render_to_response | |
from django import forms | |
from functools import wraps, partial | |
class CheckboxChallengeForm(forms.Form): | |
"""Simple checkbox form.""" | |
confirm = forms.BooleanField() | |
##: Default template to use for confirm action | |
DEFAULT_TEMPLATE = "confirmations/default.html" | |
##: Default context to be passed to template. | |
DEFAULT_CONTEXT = { | |
"title": _("Confirmation Required"), | |
"question": _("Are you sure you want to do that?"), | |
"form": CheckboxChallengeForm(), | |
"error": _("Confirm your action."), | |
} | |
##: Identity function for text processors. | |
DEFAULT_PROCESSOR = lambda x, *args, **kw: x | |
##: Challenge function suitable for making sure the checkbox is checked. | |
DEFAULT_CHALLENGE = lambda x, *args, **kw: x == "on" | |
##: Processor mappings | |
DEFAULT_PROCESSORS = { | |
} | |
def confirmation_required(fn=None, | |
parameter_name="confirm", | |
context=DEFAULT_CONTEXT, | |
processors=DEFAULT_PROCESSORS, | |
challenge=DEFAULT_CHALLENGE, | |
template=DEFAULT_TEMPLATE): | |
""" | |
Decorator which requires user to check a box before the view is served. | |
This is an extensible decorator which can serve as a basis for a variety of | |
purposes. | |
Arguments: | |
parameter_name: the GET parameter name to check | |
context: the context to pass to the template | |
processors: a dict of callables to help process the context | |
challenge: a challenge function | |
template: the template to render to | |
""" | |
if fn == None: | |
return partial(confirmation_required, | |
parameter_name=parameter_name, | |
context=context, | |
processors=processors, | |
challenge=challenge, | |
template=template) | |
@wraps(fn) | |
def decorator(request, *args, **kwargs): | |
response = request.GET.get(parameter_name) | |
if challenge(response, *args, **kwargs): | |
return fn(request, *args, **kwargs) | |
template_context = dict(DEFAULT_CONTEXT) | |
template_context.update(context) | |
for name, processor in processors.items(): | |
value = template_context.get(name) | |
template_context[name] = processor(value, *args, **kwargs) | |
return render_to_response(template, template_context, | |
context_instance=RequestContext(request)) | |
return decorator |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment